A signal that is not received using a bash script is triggered using the system (3)

I have a bash script that waits 3 minutes before the daemon signal. During these 3 minutes I need him to exit if he received SIGINT .

My current script works when run from bash, however, when I run it from another (C) program using a call to system() , it does not exit when it is sent to SIGINT .

Here is my current script:

 #!/bin/bash trap 'exit' INT sleep 180 & wait trap '' INT /etc/init.d/myd sync 

This is how I run it:

 kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x "myscript.sh" > /dev/null && /opt/my/scripts/myscript.sh & 

The same liner does not work when launched using the system() call.

PS: Basically, I use this mechanism to run the /etc/init.d/myd sync command after it was only called for the last time, if it was called several times in 3 minutes.

EDIT 1

C code as requested:

 system("kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x \"myscript.sh\" > /dev/null && /opt/my/scripts/myscript.sh &"); 

The C program is quite huge (spanning dozens of files), so I just insert a specific call here. The program is supposed to run as a daemon, but I get this problem even if I don't run it as a daemon (using the command line).

I can reproduce this with the following trivial C code:

 #include <stdlib.h> int main(int argc, char *argv[]) { system("kill -INT `pgrep myscript.sh` 2>/dev/null; ! pgrep -x \"myscript.sh\" > /dev/null && /opt/my/scripts/myscript.sh &"); return 0; } 
+5
source share
1 answer

Why (Updated):

  • The actual name of the bash process, not myscript.sh
  • pgrep can match itself through sh in a call to system()
  • SIGINT just doesn't play well when a script runs in the background. (SIGUSR1 was used instead)

After some discussion and testing on different operating systems, missing the intricacies, it really came down to:

  • When you run the script from tty, ps display this:
 46694 s001 S+ 0:00.01 /bin/bash /opt/my/scripts/myscript.sh 
  1. When you run the script from the system() call (via sh ), ps display this:
 46796 s002 S 0:00.00 /bin/bash /opt/my/scripts/myscript.sh 

In the ps manual:

    •   state The first character indicates the run state of the process: 
      
        S Marks a process that is sleeping for less than about 20 seconds 
      Additional characters after these, if any, indicate additional state information:

      + The process is in the foreground process group of its control terminal.

So, processes without + did not play with SIGINT.

Turns out we can catch SIGUSR1 and send it kill -USR1


Working test on Ubuntu 16.04 and Mac OS X 10.12:

cmon.c

  •  #include int main(int argc, char *argv[]) { system("mypid=`cat /opt/my/scripts/myscript.pid` ; ps -p $mypid > /dev/null && kill -USR1 $mypid 2>/dev/null ; mypid=`cat /opt/my/scripts/myscript.pid` ; ps -p $mypid > /dev/null || /opt/my/scripts/myscript.sh &"); return 0; } 

/opt/my/scripts/myscript.sh

  •  #!/bin/bash 
    #process for this instance of bash bashpid="$$"

    #ensure single instance mypid="$(cat "$(dirname "$0")/myscript.pid" 2>/dev/null)" ps -p $mypid &> /dev/null && (echo "already running, now going to exit this instance" ; echo "seems we never see this message, that good, means the system() call is only spawning a new instance if there no process match." ; kill -9 "$bashpid")

    #set pidfile for this instance echo "$bashpid" > "$(dirname "$0")/myscript.pid"
    trap 'echo "BYE" ; exit' SIGUSR1 sleep 5 & # 30 seconds for testing wait trap '' SIGUSR1
    echo "Sitting here in limbo land" & while true ; do sleep 5 ; done

Testing

A simple line to loop the binary ./cmon and make sure that every time we get a different process (while inside the timeout):

 unset i ; until [[ i -eq 5 ]] ; do ./cmon ; ps ax | grep bash.*myscript.sh | grep -v grep | awk -F ' ' '{print $1 " " $6}' ; sleep 1 ; (( i ++ )) ; done 

The same line can be run after a timeout to verify that all process numbers are the same

The built-in full unit test assembly and test sequence can be found here: link ybin

And a demo version of this program:

enter image description here

Process notes :

  • Scenarios are modified only for testing convenience (i.e. 10 second timeout).
  • A separate instance check is added redundantly (the trigger of a single instance in the myscript.sh file should never run .. and never seem to)

Refresh to follow when OP confirms final work

+1
source

All Articles