RaspISteve
Posts: 98
Joined: Wed Oct 24, 2012 9:15 pm
Location: Cheltenham, UK

Problems with mixing WiringPi Interrupts with forking to a child process

Sun Nov 04, 2018 12:34 am

Guys,

I have a little program which connects to a signal using a controlled relay and spawns a child process that calls "aplay..." with parameters to play an appropriate voice message before disconnecting the relay when the message plays out.

Rather that fire off the "aplay..." and wait enough time hoping its finished before opening the relay I included a signal handler and registered it to the SIGCHLD event. SIGCHLD gets triggered when your child process terminates. The aim being to fork the "aplay..." process off as a child process and, as the parent, wait for it to complete based on getting and handling SIGCHLD. I had already tested forcing early termination (killing) of the child by setting the time-out value to lower value.

It all work very nicely until I decided to add an input source to terminate the "aplay..." message early if a signal tells me its been rejected/ignored.

Plan A was to hang an interrupt handler on a GPIO pin and use it to to trigger an early exit from the wait loop and kill the child process.

Simply including:

Code: Select all

if ( wiringPiISR (CALL_HANG_DETECT_IP_PIN, INT_EDGE_FALLING, &myInterrupt) < 0 ) {

        fprintf (stderr, "\nUnable to setup ISR.\n");
        exit(0);
 } 
Seems to trigger an unexpected SIGCHLD signal. This satisfies the parent process and it exits leaving the "aplay..." output to continue until its finished.

Note: I include the option to put "aplay..." in a script. This needs a bit of cleaver to ensure both script AND any processes it kicks off get killed at the right time. Without the second kill the script dies but the enclosed "aplay..." runs to termination.

The fork() process I use is ripped from the usual place:

Code: Select all

if ((child_pid = fork()) == 0) {
// see : https://stackoverflow.com/questions/15692275/how-to-kill-a-process-tree-programmatically-on-linux-using-c

    setpgid(0, 0);      // this plus the two Kills below...
    if (execve(my_argv[0], (char **)my_argv , NULL) == -1) {
    
        perror("\nPi Child process failed to launch.");
        child_process_exited = 0xFF;    // show child process as exited 
     }                       // (well it never got going)
 }
Then I go into a while loop waiting on a signal from the signal handler (not shown)

Code: Select all

timeout = 30;        // its a 1 sec. loop, Timout after 30 seconds.
caller_hang = 0;
while((child_process_exited == 0) && (--timeout) && (caller_hang == 0)) {
        sleep(1);      // time out for a 1-sec...
 }

 if ((timeout == 0) || (caller_hang)) {  // either I timed out or Caller hung-up
        // the following is per the URL above and aims to kill the children of the script.
        kill(-child_pid, SIGKILL);      // kill the child
        sleep(2);
        kill(-child_pid, SIGKILL);      // now deliver the coup de grace and kill everything on
 }
child_process_exited = 0;
A debug message from the signal handler tells me it gets a SIGCHLD before "aplay..." starts. I can only assume there is another child process in there somewhere, perhaps the WiringPiISR magic which is generating the early signal. Certainly the two kills don't kill the "aplay..." process.

The code shown is wrapped with the relay drive on and relay drive off. With the ISR the relay clicks on then off followed by the message play. Without the ISR the relay drives on, message plays fully and the relay clicks off.

What al I missing here?

Simply removing the WiringPi ISR setup call solves my problem. Current Plan B solution is to poll the caller_hang GPIO input.

Sorry this is a bit long.
Share and Enjoy.

User avatar
gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

Re: Problems with mixing WiringPi Interrupts with forking to a child process

Wed Nov 07, 2018 12:10 pm

I've no idea why your program behaves as it does (and not really got time to look that closely at it. sorry), however note that wiringPiISR calls fork() and pthread_create() itself. These may or may not be having some sort of side-effect on your code.

-Gordon
--
Gordons projects: https://projects.drogon.net/

RaspISteve
Posts: 98
Joined: Wed Oct 24, 2012 9:15 pm
Location: Cheltenham, UK

Re: Problems with mixing WiringPi Interrupts with forking to a child process

Mon Nov 19, 2018 10:03 am

Gordon,

Thank you for your update and WiringPi.

Turns out I haven't had the time to go investigate why it wouldn't work either. Just thought I'd share my experience for the benefit of others.

My program simply polls a GPIO pin but includes a sleep so as not of hog anything.
Share and Enjoy.

Return to “C/C++”