Hi,
When playing with the Yarp bindings, I have found that a module segfaults when calling yarp.Network.fini(), but only if a RFModule is used.
Minimum working example:
#!/usr/bin/env python
import yarp
import time
import sys
print sys.argv
class TestMod(yarp.RFModule):
def configure(self, rf):
moduleName = rf.check("name", yarp.Value("test")).asString()
self.setName(moduleName)
self.count = 0
return True
def respond(self, command, reply):
return True
def interruptModule(self):
print "Interrupt"
return True
def close(self):
print "Close"
return True
def getPeriod(self):
return 1.0
def updateModule(self):
time.sleep(0.5)
self.count = self.count + 1
print self.count
if self.count < 3:
return True
else:
return False
yarp.Network.init()
rf = yarp.ResourceFinder()
rf.setVerbose(True);
rf.setDefaultContext("test");
rf.setDefaultConfigFile("config.ini");
rf.configure(sys.argv)
mod = TestMod()
mod.runModule(rf)
yarp.Network.fini()
This leads to the following segfault:
||| did not find config.ini
yarp: cannot read from config.ini
1
2
3
[INFO]RFModule closing.
Close
[INFO]RFModule finished.
Program received signal SIGSEGV, Segmentation fault.
__new_sem_wait (sem=0x8) at sem_wait.c:26
26 sem_wait.c: No such file or directory.
(gdb) thread apply all bt
Thread 1 (Thread 0x7ffff7f9f700 (LWP 4660)):
#0 __new_sem_wait (sem=0x8) at sem_wait.c:26
#1 0x00007ffff521a34c in yarp::os::impl::ThreadImpl::isRunning() ()
from /usr/local/src/robot/install/yarp/lib/python2.7/dist-packages/../../libYARP_OS.so.1
#2 0x00007ffff5219bf9 in ThreadCallbackAdapter::close() ()
from /usr/local/src/robot/install/yarp/lib/python2.7/dist-packages/../../libYARP_OS.so.1
#3 0x00007ffff52199a2 in yarp::os::Thread::stop() () from /usr/local/src/robot/install/yarp/lib/python2.7/dist-packages/../../libYARP_OS.so.1
#4 0x00007ffff51e092e in yarp::os::RFModule::~RFModule() ()
from /usr/local/src/robot/install/yarp/lib/python2.7/dist-packages/../../libYARP_OS.so.1
#5 0x00007ffff654e69b in _wrap_delete_RFModule () from /usr/local/src/robot/install/yarp/lib/python2.7/dist-packages/_yarp.so
#6 0x00000000004b0cb3 in PyObject_Call ()
#7 0x00000000004b97fa in PyObject_CallFunctionObjArgs ()
#8 0x00007ffff643e610 in SwigPyObject_dealloc () from /usr/local/src/robot/install/yarp/lib/python2.7/dist-packages/_yarp.so
#9 0x00000000004fd4e6 in ?? ()
#10 0x00000000004a0d22 in PyDict_SetItem ()
#11 0x0000000000502bf3 in _PyModule_Clear ()
#12 0x000000000050275c in PyImport_Cleanup ()
#13 0x0000000000500489 in Py_Finalize ()
#14 0x000000000049df2f in Py_Main ()
#15 0x00007ffff7811830 in __libc_start_main (main=0x49dab0 <main>, argc=2, argv=0x7fffffffd588, init=<optimised out>, fini=<optimised out>,
rtld_fini=<optimised out>, stack_end=0x7fffffffd578) at ../csu/libc-start.c:291
#16 0x000000000049d9d9 in _start ()
When removing the last line (yarp.Network.fini()), all is good.
It seems like that in ThreadImpl this code is causing the problem - it seems like threadMutex is deleted somewhere and then cannot be accessed anymore.
bool ThreadImpl::isRunning()
{
threadMutex->wait();
bool b = active;
threadMutex->post();
return b;
}
Best, Tobi
By the way, this also happens when creating a yarp.Network object:
yn = yarp.Network()
rf = yarp.ResourceFinder()
rf.setVerbose(True);
rf.setDefaultContext("test");
rf.setDefaultConfigFile("config.ini");
rf.configure(sys.argv)
mod = TestMod()
mod.runModule(rf)
Remainder: when we fix this bug we should add the regression test (that is basically already attached to the bug report) in https://github.com/robotology/yarp/tree/master/bindings/tests/python .
Just to confirm: I can reproduce the error when calling yarp.Network.fini(). I hadn't called this function beforehand, so I didn't experience the problem. But I guess I'm supposed to call this function prior to leaving main.
@frank-foerster: Yes, at least in C++ it's good practice to either call yarp.Network.fini() or create a yarp.Network object which automatically takes care of this when it's being destroyed.
@traversaro: Maybe the code snippet can also be added as example on how to use RFModule from Python.
I think that the RFModule might be using some object coming from the network initialization, but without calling init and fini internally.
The order of destruction of the objects appears to be different from the "C++" order
initRFModule::RFModulefiniRFModule::~RFModuleor using the network
Network::NetworkRFModule::RFModuleNetwork::~NetworkRFModule::~RFModulePerhaps this is due to the %feature("director") yarp::os::RFModule; in the .i?
Adding this seems to fix the issue as well:
I want to investigate this a little bit better before committing this, though.
diff --git a/src/libYARP_OS/src/RFModule.cpp b/src/libYARP_OS/src/RFModule.cpp
index 2894ed3..461879b 100644
--- a/src/libYARP_OS/src/RFModule.cpp
+++ b/src/libYARP_OS/src/RFModule.cpp
@@ -350,6 +350,7 @@ static void handler_sigbreak(int sig) {
RFModule::RFModule() {
+ yarp::os::Network::initMinimum();
implementation = new RFModuleHelper(*this);
stopFlag = false;
@@ -376,6 +377,7 @@ RFModule::~RFModule() {
delete &HELPER(implementation);
implementation = YARP_NULLPTR;
}
+ yarp::os::Network::finiMinimum();
}
@drdanz have you committed these lines? Have they resolved the problem?
Nope, this was never committed, I don't remember why... @Tobias-Fischer Have you tried the patch above? Did this solve your problem?
Hi @drdanz,
Yes the above patch fixes the problem. All working fine in that case :). Is it okay for you to commit that patch to yarp?
Best, Tobi
I think it is. I will test it a little bit more and commit it in the next few days