Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Keep a "system" process running if script is prematurely exited?

by westrock2000 (Beadle)
on Jun 17, 2010 at 04:10 UTC ( [id://845138]=perlquestion: print w/replies, xml ) Need Help??

westrock2000 has asked for the wisdom of the Perl Monks concerning the following question:

Consider the following
system("kedit &"); #or `kedit &` chomp(input=<>); exit;
If I execute the command it will open a kedit and continue to a user input prompt. If I hit enter it will exit the script and the kedit will continue to stay open.

But if I were to close out the xterm while it was waiting for $input, the kedit application will also close out.

How can I prevent the kedit from being closed if the script is prematurely exited?

Replies are listed 'Best First'.
Re: Keep a "system" process running if script is prematurely exited?
by ikegami (Patriarch) on Jun 17, 2010 at 04:28 UTC

    I believe the child needs to disconnect STDIN, STDOUT and STDERR from the terminal.

    use IPC::Open3 qw( open3 ); open(local *TO_CHLD, '<', '/dev/null') or die; open(local *FR_CHLD, '>', '/dev/null') or die; open3('>&TO_CHLD', '<&FR_CHLD', '<&FR_CHLD', 'kedit');

    It might also need to call POSIX's setsid. I'm not sure what it does ( but I think it's what later-mentioned disown does ).

    Update: It's the other way around. setsid is required, but replacing STDIN, STDOUT and STDERR is probably not.

      I'm not sure what it does

      setsid(2) creates a new session and connection to the controlling terminal is lost. The calling process becomes the new session and process group leader. This is commonly used to disconnect from a terminal when writing a daemon.

      I doubt it is relevant here. The editor being launched is an X-Windows application which does not use STDIN/OUT/SHAKEITALLABOUT. Is it Friday yet?
        Copying the docs isn't very useful. I still have no idea what "disconnecting from a terminal" means.
Re: Keep a "system" process running if script is prematurely exited?
by cdarke (Prior) on Jun 17, 2010 at 07:37 UTC
    UNIX shells vary, but most send a SIGHUP to the child when the process ends. There are several ways of getting your child process to ignore SIGHUP. A shell type method is to use the nohup(1) program,:
    system("nohup kedit &"); #or `kedit &`
    another is to set
    $SIG{HUP} = 'IGNORE';
    in your perl before the system command.

    However there might be a simpler way. You can supress this default action in bash using
    shopt -u huponexit

    Tested using CentOS 5.2, Perl 5.12.0, bash 3.2.25(1) (where the default for huponexit is off), KEdit 1.3.
      The nohup command worked very easily. Thanks.
Re: Keep a "system" process running if script is prematurely exited?
by Anonymous Monk on Jun 17, 2010 at 04:14 UTC
Re: Keep a "system" process running if script is prematurely exited?
by sflitman (Hermit) on Jun 17, 2010 at 05:44 UTC
    Under bash, you can use the disown command to detach it from the process and make it owned by the top-level process init. From bash:
    # gedit & # disown $!
    Where $! is the last process id. To do this in Perl, I tried this:
    # perl -e 'system q{gedit &}'
    It starts gedit in its own window on my Ubuntu system and returns to the shell prompt. Then I close the terminal, and voila! gedit is still running. Can anyone tell us why disown is not needed in this case?

    HTH,
    SSF

      Probably because bash shell option huponexit is set to off (see shopt for option settings).
      By the way, disown -h will supress HUP for a specific job, see help disown
      Probably because the perl process that launched gedit is finished (isn't connected to the shell anymore ie STDIN/STDOUT/STDERR are closed)

      You can confirm by comparing strace/truss output with

      perl -e 'system q{gedit &} scalar <>;'
Re: Keep a "system" process running if script is prematurely exited?
by JavaFan (Canon) on Jun 17, 2010 at 14:28 UTC
    You may want to read the Complete Dissociation of Child from Parent section in perlipc.
Re: Keep a "system" process running if script is prematurely exited?
by Argel (Prior) on Jun 17, 2010 at 19:31 UTC
    The following code to create a daemon may be useful (though e.g. you may want to leave your PATH alone).
    use IO::Socket; use POSIX qw(WNOHANG setsid); sub daemonize { $SIG{CHLD} = 'IGNORE'; # Configure to autoreap zombies die "Can't fork" unless defined ( my $child = fork ); # FORK +<<<<<<<<<<<< CORE::exit(0) if $child; # Parent exits setsid(); # Become session leader open( STDIN, "</dev/null" ); # Detach STDIN from shell open( STDOUT, ">/dev/null" ); # Detach STDOUT from shell open( STDERR, ">&STDOUT" ); # Detach STDERR from shell chdir '/tmp'; # Change working directory umask(0); # Reset umask $ENV{PATH} = '/bin:/sbin:/usr/sbin'; # Reset PATH }

    WARNING: Verify your system supports autoreaping of zombies!!!!!

    You can read more in these threads: See also Re: Perl daemon that runs another daemon, Running Perl scripts from ssh, how to make a demon in perl?, and Persistent perl.

    Elda Taluta; Sarks Sark; Ark Arks

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://845138]
Approved by lidden
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (5)
As of 2025-02-18 06:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found