How can I kill Perl system calls when the main script is killed?

Past answers to these questions have focused on views:

  • terminate the background process when the shell script is completed
  • How to make a child die after exiting a parent?
  • Are child processes created with fork () automatically killed when the parent is destroyed?

For that matter, I'm just asking about calls to the "system" function.

Let's say I have a script called sleep.pl:

use strict; use warnings; sleep(300); 

Then I have a script called kill.pl

 use strict; use warnings; system("sleep.pl"); 

I run kill.pl and use ps. I find the process id kill.pl and kill it (not using kill -9, just normal kill)

sleep.pl was still sleeping.

I assume that the solution to my question is related to the SIG handler, but what do I need to put in the handler to kill the child process?

+6
perl kill
source share
3 answers

Use setsid to make your process the new leader of the group. Then you can send kill to the group ID and kill all processes belonging to the group. All processes that you spawn from the leader process inherit the group identifier and belong to your newly created group. So sending a kill to a group will kill them all. The only difficult thing is to be able to use setsid, you have to close your standard and display it, since this is a requirement for setid.

+3
source share
 use strict; use warnings; setpgrp $$, 0; system("sleep.pl"); END {kill 15, -$$} 

But if you need this approach, you are doing something wrong. You must not do this. Launch and destroy your killing process correctly.

 $ perl -e 'system("sleep 100")' & [1] 11928 $ ps f PID TTY STAT TIME COMMAND 4564 pts/1 Ss 0:01 /bin/bash 11928 pts/1 S 0:00 \_ perl -e system("sleep 100") 11929 pts/1 S 0:00 | \_ sleep 100 11936 pts/1 R+ 0:00 \_ ps f $ kill %1 [1]+ Terminated perl -e 'system("sleep 100")' $ ps f PID TTY STAT TIME COMMAND 4564 pts/1 Rs 0:01 /bin/bash 11949 pts/1 R+ 0:00 \_ ps f 

How it works? Shell (bash in my case) should set your process as a group leader if you run in the background. Then if you use kill %? , the syntax shell kills the group correctly. Compare this:

 $ perl -e 'system("sleep 100")' & [1] 12109 $ ps f PID TTY STAT TIME COMMAND 4564 pts/1 Rs 0:01 /bin/bash 12109 pts/1 S 0:00 \_ perl -e system("sleep 100") 12113 pts/1 S 0:00 | \_ sleep 100 12114 pts/1 R+ 0:00 \_ ps f $ kill 12109 [1]+ Terminated perl -e 'system("sleep 100")' $ ps f PID TTY STAT TIME COMMAND 4564 pts/1 Ss 0:01 /bin/bash 12124 pts/1 R+ 0:00 \_ ps f 12113 pts/1 S 0:00 sleep 100 

But kill %? works as follows:

 $ perl -e 'system("sleep 100")' & [1] 12126 $ ps f PID TTY STAT TIME COMMAND 4564 pts/1 Rs 0:01 /bin/bash 12126 pts/1 S 0:00 \_ perl -e system("sleep 100") 12127 pts/1 S 0:00 | \_ sleep 100 12128 pts/1 R+ 0:00 \_ ps f $ kill -12126 [1]+ Terminated perl -e 'system("sleep 100")' $ ps f PID TTY STAT TIME COMMAND 4564 pts/1 Ss 0:01 /bin/bash 12130 pts/1 R+ 0:00 \_ ps f 
+3
source share

Your question is indeed a concrete example of the more general "ways to ensure that the child dies when the parent dies." There just can't get around this. There is nothing special about system (); he simply expands the child process and waits for his exit.

system () is something like this:

 sub system { my $kidpid = fork; if ( $kidpid ) { waitpid $kidpid; # parent process blocks here waiting for the child process to return } else { exec( @_ ); } } 

Killing a process group is your only option.

+2
source share

All Articles