How to quit an application running with a TaskBrowser ?

We would like to deploy an application with the TaskBrowser running.
We need to be able to stop the application, in a proper way (to release all the memory and to let the console working).
We can do this with typing “quit” in the TaskBrowser, but we have to do this also from “inside” the application (when a button is pushed).

My analysis is this :
The main is blocked when calling the TaskBrowser.loop().
The loop() method in the TaskBrowser never ends, except if we enter “quit”. This method is blocked by a system call while reading a line.

I think the only way to exit from this is :
send a OS signal to the main thread to exit from the system call.
Store that information in the OS signal handler ( endApplicaton = true )
in TaskBrowser::loop replace while(1) by while(endApplicaton == false)

Is there a better to do this ?
Has someone already developed something like this ?

Best regards
Nicolas

How to quit an application running with a TaskBrowser ?

On Monday 19 January 2009 16:04:12 nicolas [dot] mabire [..] ... wrote:
> We would like to deploy an application with the TaskBrowser running.
> We need to be able to stop the application, in a proper way (to release all
> the memory and to let the console working). We can do this with typing
> “quit” in the TaskBrowser, but we have to do this also from “inside” the
> application (when a button is pushed).
>
> My analysis is this :
> The main is blocked when calling the TaskBrowser.loop().
> The loop() method in the TaskBrowser never ends, except if we enter “quit”.
> This method is blocked by a system call while reading a line.
>
> I think the only way to exit from this is :
> send a OS signal to the main thread to exit from the system call.
> Store that information in the OS signal handler ( endApplicaton = true )
> in TaskBrowser::loop replace while(1) by while(endApplicaton == false)
>
> Is there a better to do this ?
> Has someone already developed something like this ?

When we wanted similar behaviour, we setup the application as a CORBA server
and started a 'ctaskbrowser', which is then 'independent' of the running
application (although it needs to restart/be killed as well when the server
quits).

Sending a signal to the process is always tricky. The signal is delivered to
all threads, even when you install a handler (if I recall correctly). So it
may be to disruptive to the whole application and not allow 'nice' cleanup
after all. On the other hand, I can't think of another way to wake the
taskbrowser up in its loop() function. We'd at least need to test how the
*Thread classes of the RTT respond to the signal.

Peter

An (almost) nice solution without CORBA.

Thank you Peter for your answer.

I agree with you that running an independent TaskBrowser throw a CORBA server is the best solution...

I also agree that signal delivery is always something difficult in multi-threaded applications (see man 2 kill). That is why I always use int pthread_kill(pthread_t thread, int sig) when I want a signal to be handled in a particular thread. This function exists under linux. I do not know how much POSIX it is (and if it is working like this for other OS).

So here what I have replaced in the main function tb.loop, by a function that : create a thread, which handle a real-time signal waits for the termination of that thread. The signal handle of that thread cleans up readline and does a pthread_exit.

I can now “kill” the TaskBrowser with pthread_kill. Getting out from loop creates only a small memory deallocation memory problem. Valgrind says :

==18562== 4 bytes in 1 blocks are definitely lost in loss record 1 of 38
...
==18562==    by 0x4ADA248: OCL::TaskBrowser::evalCommand(std::string&) (TaskBrowser.cpp:1257)
==18562==    by 0x4AE7C7F: OCL::TaskBrowser::loop() (TaskBrowser.cpp:696)
==18562==    by 0x806745E: threadTaskBrowser(void*) (main.cpp:106)
==18562==    by 0x46F30BC: start_thread (in /lib/tls/libpthread-2.3.6.so)
==18562==    by 0x4D93ACD: clone (in /lib/tls/libc-2.3.6.so)
That is due to the line :
>>>       CommandInterface* com = _parser.parseCommand( comm, context, true ).first; 
From my point of view, this is not a big problem...

Concerning side effects with *Thread classes of the RTT about signal delivery, as I use pthread_kill, I believe that there should be no problem (others threads will not receive the signal) – except if they would deal with signals, but I haven't seen this in src/os.

The main problem of that solution is that I have to make some system calls outside orocos...

Nicolas

An (almost) nice solution without CORBA.

On Wednesday 21 January 2009 17:49:02 nicolas [dot] mabire [..] ... wrote:
> Thank you Peter for your answer.
>
> I agree with you that running an independent TaskBrowser throw a CORBA
> server is the best solution...
>
> I also agree that signal delivery is always something difficult in
> multi-threaded applications (see man 2 kill). That is why I always use int
> pthread_kill(pthread_t thread, int sig) when I want a signal to be handled
> in a particular thread. This function exists under linux. I do not know how
> much POSIX it is (and if it is working like this for other OS).

It certainly won't work on Windows, unless when using mingw32, and even
then...

>
> So here what I have replaced in the main function tb.loop, by a function
> that : create a thread, which handle a real-time signal
> waits for the termination of that thread.
> The signal handle of that thread cleans up readline and does a
> pthread_exit.
>
> I can now “kill” the TaskBrowser with pthread_kill.

But who calls pthread_kill ? Is your solution usable for other users ?

> Getting out from loop creates only a small memory deallocation memory
> problem. Valgrind says :
>
> ==18562== 4 bytes in 1 blocks are definitely lost in loss record 1 of 38
> ...
> ==18562== by 0x4ADA248: OCL::TaskBrowser::evalCommand(std::string&)
> (TaskBrowser.cpp:1257) ==18562== by 0x4AE7C7F: OCL::TaskBrowser::loop()
> (TaskBrowser.cpp:696) ==18562== by 0x806745E: threadTaskBrowser(void*)
> (main.cpp:106) ==18562== by 0x46F30BC: start_thread (in
> /lib/tls/libpthread-2.3.6.so) ==18562== by 0x4D93ACD: clone (in
> /lib/tls/libc-2.3.6.so)
>
> That is due to the line :
> >>> CommandInterface* com = _parser.parseCommand( comm, context, true
> >>> ).first;
> >
> >From my point of view, this is not a big problem...

You're exiting the app, so I agree.

>
> Concerning side effects with *Thread classes of the RTT about signal
> delivery, as I use pthread_kill, I believe that there should be no problem
> (others threads will not receive the signal) – except if they would deal
> with signals, but I haven't seen this in src/os.

They don't. Libraries that generate signals often don't work nicely together
with other libraries...

>
> The main problem of that solution is that I have to make some system calls
> outside orocos...

Could you clarify that ?

Peter

An (almost) nice solution without CORBA.

Just a few lines to explain myself.
My purpose is only to have something running for *my* OS, only for exiting the application.
The fact I have to make some system calls outside Orocos (I mean without going throw fosi) makes this certainly *NOT* running for other OS, and as Herman says, should not be used to start/stop activities.
In detail, I have created a main which launch a thread for the TaskBrowser and start a specific deployer, derived from OCL::Deployer. It reacts to an event to stop the application : stop all the components (like the standard Deployer), and then, send a signal to that thread. The handler, then stop the TaskBrowser.
It works fine, so, even if it is not clean, it will be enough for me at this moment (as it is used only at the end of the application). The advantage is that I do not have to apply any patch on orocos.

Nicolas

An (almost) nice solution without CORBA.

On Wed, 21 Jan 2009, nicolas [dot] mabire [..] ... wrote:

> Thank you Peter for your answer.
>
> I agree with you that running an independent TaskBrowser throw a CORBA
> server is the best solution...
>
> I also agree that signal delivery is always something difficult in
> multi-threaded applications (see man 2 kill).

It is not only difficult but extremely dangerous_! I strongly advice you
never to use thread functionalities to start/stop an activity...

Herman

> That is why I always use int pthread_kill(pthread_t thread, int sig) when I want a signal to be handled in a particular thread. This function exists under linux. I do not know how much POSIX it is (and if it is working like this for other OS).
>
> So here what I have replaced in the main function tb.loop, by a function that :
> create a thread, which handle a real-time signal
> waits for the termination of that thread.
> The signal handle of that thread cleans up readline and does a pthread_exit.
>
> I can now “kill” the TaskBrowser with pthread_kill.
> Getting out from loop creates only a small memory deallocation memory problem. Valgrind says :
>
> ==18562== 4 bytes in 1 blocks are definitely lost in loss record 1 of 38
> ...
> ==18562== by 0x4ADA248: OCL::TaskBrowser::evalCommand(std::string&) (TaskBrowser.cpp:1257)
> ==18562== by 0x4AE7C7F: OCL::TaskBrowser::loop() (TaskBrowser.cpp:696)
> ==18562== by 0x806745E: threadTaskBrowser(void*) (main.cpp:106)
> ==18562== by 0x46F30BC: start_thread (in /lib/tls/libpthread-2.3.6.so)
> ==18562== by 0x4D93ACD: clone (in /lib/tls/libc-2.3.6.so)
>
> That is due to the line :
>
>>>> CommandInterface* com = _parser.parseCommand( comm, context, true ).first;
>
>> From my point of view, this is not a big problem...
>
> Concerning side effects with *Thread classes of the RTT about signal delivery, as I use pthread_kill, I believe that there should be no problem (others threads will not receive the signal) – except if they would deal with signals, but I haven't seen this in src/os.
>
> The main problem of that solution is that I have to make some system calls outside orocos...
>
> Nicolas
>