Quantcast

Ensure NSTask terminates when parent application does

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Ensure NSTask terminates when parent application does

Ian Levesque-3
Hi,

I have a RubyCocoa application that runs a process in the background  
using NSTask.  I would like to ensure that it never leaves that  
background process behind after quitting. Simply terminating the task  
when the application gets ready to quit works for typical cases, but  
I'd like to prevent it from staying open even if I uncleanly terminate  
the parent process.

I found this at http://www.cocoadev.com/index.pl?NSTaskTermination :


#include <unistd.h>
NSTask * task = ... // setup task
pid_t group = setsid();
if (group == -1) {
        group = getpgrp();
}
[task launch];
if (setpgid([task processIdentifier], group) == -1) {
        NSLog(@"unable to put task into same group as self");
}


Which puts the child process into a new process group with the parent  
process.  Great.  I translated this to RubyCocoa like this:


@sid = Process.setsid
@sid = Process.getpgrp if @sid == -1
@task = OSX::NSTask.new
...
@task.launch
Process.setpgid(@task.processIdentifier, @sid)


The problem is that I always get a permissions error on "setsid" and  
"setpgid."  Which leads me to believe that the example from CocoaDev  
is probably totally broken in the first place.

Does anyone know what's wrong, or another approach that will ensure  
that my NSTask never gets left behind?

Thanks,
-Ian


_______________________________________________
MacOSX-dev mailing list
[hidden email]
http://www.omnigroup.com/mailman/listinfo/macosx-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Ensure NSTask terminates when parent application does

John Harte

On Mar 14, 2009, at 3:15 AM, Ian Levesque wrote:

> Hi,
>
> I have a RubyCocoa application that runs a process in the background  
> using NSTask.  I would like to ensure that it never leaves that  
> background process behind after quitting. Simply terminating the  
> task when the application gets ready to quit works for typical  
> cases, but I'd like to prevent it from staying open even if I  
> uncleanly terminate the parent process.
>

I use this to kill my child process when the parent goes away:

void* WatchForParentTermination (void* arg) {
        pid_t ppid = getppid (); // get parent pid

        int kq = kqueue ();
        if (kq != -1) {
                struct kevent procEvent; // wait for parent to exit
                EV_SET (&procEvent, // kevent
                                ppid, // ident
                                EVFILT_PROC, // filter
                                EV_ADD, // flags
                                NOTE_EXIT, // fflags
                                0, // data
                                0); // udata

                kevent (kq, &procEvent, 1, &procEvent, 1, 0);
        }
        printf ("drTap Terminating--Parent Process Terminated\n");
        exit (0);
        return 0;
}


in main:

        pthread_t thread;
        int error = pthread_create (&thread, 0, WatchForParentTermination, 0);



_______________________________________________
MacOSX-dev mailing list
[hidden email]
http://www.omnigroup.com/mailman/listinfo/macosx-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Ensure NSTask terminates when parent application does

Ian Levesque-3
Thanks for the code sample.  That looks like a drop-in solution if you  
have the source code to the background process. The problem is that I  
don't have any control over the source code of the background  
process.  I found a couple other email threads on this issue and it  
appears that everyone ended up adding code to the background process  
to watch for the parent's termination.

Am I just out of luck?  Those poor helpless end users with orphaned  
processes... :-(

-Ian

On Mar 14, 2009, at 12:29 PM, John Harte wrote:

>
> On Mar 14, 2009, at 3:15 AM, Ian Levesque wrote:
>
>> Hi,
>>
>> I have a RubyCocoa application that runs a process in the  
>> background using NSTask.  I would like to ensure that it never  
>> leaves that background process behind after quitting. Simply  
>> terminating the task when the application gets ready to quit works  
>> for typical cases, but I'd like to prevent it from staying open  
>> even if I uncleanly terminate the parent process.
>>
>
> I use this to kill my child process when the parent goes away:
>
> void* WatchForParentTermination (void* arg) {
> pid_t ppid = getppid (); // get parent pid
>
> int kq = kqueue ();
> if (kq != -1) {
> struct kevent procEvent; // wait for parent to exit
> EV_SET (&procEvent, // kevent
> ppid, // ident
> EVFILT_PROC, // filter
> EV_ADD, // flags
> NOTE_EXIT, // fflags
> 0, // data
> 0); // udata
>
> kevent (kq, &procEvent, 1, &procEvent, 1, 0);
> }
> printf ("drTap Terminating--Parent Process Terminated\n");
> exit (0);
> return 0;
> }
>
>
> in main:
>
> pthread_t thread;
> int error = pthread_create (&thread, 0, WatchForParentTermination,  
> 0);
>
>
>

_______________________________________________
MacOSX-dev mailing list
[hidden email]
http://www.omnigroup.com/mailman/listinfo/macosx-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Ensure NSTask terminates when parent application does

Marcel Weiher-3

On Mar 14, 2009, at 10:09 , Ian Levesque wrote:

> Thanks for the code sample.  That looks like a drop-in solution if  
> you have the source code to the background process. The problem is  
> that I don't have any control over the source code of the background  
> process.  I found a couple other email threads on this issue and it  
> appears that everyone ended up adding code to the background process  
> to watch for the parent's termination.
>
> Am I just out of luck?  Those poor helpless end users with orphaned  
> processes... :-(

Isn't this the sort of thing process groups should handle?  I guess  
the question is what sort of abnormal termination of the parent you  
are trying to deal with?  If it is due to a signal, a process group  
should, in my understanding, propagate that signal to your child  
processes.

Marcel

_______________________________________________
MacOSX-dev mailing list
[hidden email]
http://www.omnigroup.com/mailman/listinfo/macosx-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Ensure NSTask terminates when parent application does

Chris Suter-2
In reply to this post by Ian Levesque-3
Hi Ian,

On Sun, Mar 15, 2009 at 4:09 AM, Ian Levesque
<[hidden email]> wrote:
> Thanks for the code sample.  That looks like a drop-in solution if you have
> the source code to the background process. The problem is that I don't have
> any control over the source code of the background process.  I found a
> couple other email threads on this issue and it appears that everyone ended
> up adding code to the background process to watch for the parent's
> termination.
>
> Am I just out of luck?  Those poor helpless end users with orphaned
> processes... :-(

I know that NSTask spawns isolated processes. I'm not sure if you can
undo whatever it is that NSTask does to make them isolated but an
alternative approach that will work is to just use the BSD vfork ()
and exec () calls. They'll create children that will get killed when
the parent does. If you do things that way, you must take care to reap
terminated children using waitpid (or equivalent).

Also: have you posted the same question to the Cocoa-dev list?

Regards,

Chris
_______________________________________________
MacOSX-dev mailing list
[hidden email]
http://www.omnigroup.com/mailman/listinfo/macosx-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Ensure NSTask terminates when parent application does

Ian Levesque-3
In reply to this post by Marcel Weiher-3
The child doesn't appear to be in the same group by default.  My  
initial approach was to try and put them in the same group, but I get  
permissions errors doing that.

-Ian

On Mar 15, 2009, at 8:30 PM, Marcel Weiher wrote:

>
> On Mar 14, 2009, at 10:09 , Ian Levesque wrote:
>
>> Thanks for the code sample.  That looks like a drop-in solution if  
>> you have the source code to the background process. The problem is  
>> that I don't have any control over the source code of the  
>> background process.  I found a couple other email threads on this  
>> issue and it appears that everyone ended up adding code to the  
>> background process to watch for the parent's termination.
>>
>> Am I just out of luck?  Those poor helpless end users with orphaned  
>> processes... :-(
>
> Isn't this the sort of thing process groups should handle?  I guess  
> the question is what sort of abnormal termination of the parent you  
> are trying to deal with?  If it is due to a signal, a process group  
> should, in my understanding, propagate that signal to your child  
> processes.
>
> Marcel
>

_______________________________________________
MacOSX-dev mailing list
[hidden email]
http://www.omnigroup.com/mailman/listinfo/macosx-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Ensure NSTask terminates when parent application does

Ian Levesque-3
In reply to this post by Chris Suter-2
I'll look into vfork and exec, I don't have any particular attachment  
to NSTask.

I haven't posted it to Cocoa Dev, but someone else asked a similar  
question there about two weeks ago and never received a satisfactory  
solution.

Thanks,
-Ian

On Mar 15, 2009, at 9:52 PM, Chris Suter wrote:

> Hi Ian,
>
> On Sun, Mar 15, 2009 at 4:09 AM, Ian Levesque
> <[hidden email]> wrote:
>> Thanks for the code sample.  That looks like a drop-in solution if  
>> you have
>> the source code to the background process. The problem is that I  
>> don't have
>> any control over the source code of the background process.  I  
>> found a
>> couple other email threads on this issue and it appears that  
>> everyone ended
>> up adding code to the background process to watch for the parent's
>> termination.
>>
>> Am I just out of luck?  Those poor helpless end users with orphaned
>> processes... :-(
>
> I know that NSTask spawns isolated processes. I'm not sure if you can
> undo whatever it is that NSTask does to make them isolated but an
> alternative approach that will work is to just use the BSD vfork ()
> and exec () calls. They'll create children that will get killed when
> the parent does. If you do things that way, you must take care to reap
> terminated children using waitpid (or equivalent).
>
> Also: have you posted the same question to the Cocoa-dev list?
>
> Regards,
>
> Chris

_______________________________________________
MacOSX-dev mailing list
[hidden email]
http://www.omnigroup.com/mailman/listinfo/macosx-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Ensure NSTask terminates when parent application does

Markus Hitter
In reply to this post by Chris Suter-2

Am 16.03.2009 um 02:52 schrieb Chris Suter:

> an alternative approach that will work is to just use the BSD vfork  
> () and exec () calls.

There's also system() and popen(). Works like a charme, just make  
sure your users can't do unwanted things:

int ret, char * cmd[MAXPATH + 10];

ret = snprintf(cmd, sizeof(cmd) - 1, "ls %s", name);
if (ret < sizeof(cmd))
   ret = system(cmd);

If you run this with name = "$HOME" everything is fine, but with name  
= "$HOME && rm -rf $HOME" it will harm. It's a matter of validating  
user input - if user input is needed at all.


MarKus

- - - - - - - - - - - - - - - - - - -
Dipl. Ing. Markus Hitter
http://www.jump-ing.de/




_______________________________________________
MacOSX-dev mailing list
[hidden email]
http://www.omnigroup.com/mailman/listinfo/macosx-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Ensure NSTask terminates when parent application does

Ian Levesque-3
Thankfully no user input required at all, so not a problem.  One  
question though, does system/popen put the child process into the same  
process group / some other mechanism to ensure it dies if the parent  
dies? (We are now beyond my knowledge of child process handling in OS  
X...just trying to understand)

I thought system() gave the same behavior as NSTask (i.e. child gets  
reparented under launchd, not killed, if the parent dies)?  Not clear  
from the man pages.

Thanks,
-Ian

On Mar 16, 2009, at 5:35 AM, Markus Hitter wrote:

>
> Am 16.03.2009 um 02:52 schrieb Chris Suter:
>
>> an alternative approach that will work is to just use the BSD vfork  
>> () and exec () calls.
>
> There's also system() and popen(). Works like a charme, just make  
> sure your users can't do unwanted things:
>
> int ret, char * cmd[MAXPATH + 10];
>
> ret = snprintf(cmd, sizeof(cmd) - 1, "ls %s", name);
> if (ret < sizeof(cmd))
>  ret = system(cmd);
>
> If you run this with name = "$HOME" everything is fine, but with  
> name = "$HOME && rm -rf $HOME" it will harm. It's a matter of  
> validating user input - if user input is needed at all.
>
>
> MarKus
>
> - - - - - - - - - - - - - - - - - - -
> Dipl. Ing. Markus Hitter
> http://www.jump-ing.de/
>
>
>
>

_______________________________________________
MacOSX-dev mailing list
[hidden email]
http://www.omnigroup.com/mailman/listinfo/macosx-dev
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Ensure NSTask terminates when parent application does

Markus Hitter

Am 16.03.2009 um 17:52 schrieb Ian Levesque:

> Thankfully no user input required at all, so not a problem.  One  
> question though, does system/popen put the child process into the  
> same process group / some other mechanism to ensure it dies if the  
> parent dies?

I pretty much think it's executed in a subprocess, making this more  
efficient. A test would make this assumption sure, though.

> (We are now beyond my knowledge of child process handling in OS  
> X...just trying to understand)

Likely, system() behaves like in other Unixs, it's probably something  
which came with the FreeBSD heritage.


MarKus

- - - - - - - - - - - - - - - - - - -
Dipl. Ing. Markus Hitter
http://www.jump-ing.de/




_______________________________________________
MacOSX-dev mailing list
[hidden email]
http://www.omnigroup.com/mailman/listinfo/macosx-dev
Loading...