mikedice417
Posts: 5
Joined: Mon Nov 16, 2015 1:03 am

sigwait doesn't catch ctrl+c

Tue Aug 21, 2018 2:19 am

Hi,
I thought I understood the function of signals but i guess I don't. I want to block my main function until the user presses ctrl+C. After ctrl+C is pressed I want to run some cleanup code then exit the program. So, I've written some test code that shows the issue. I am working on a Mac and connected to the PI over SSH. When I compile the program below on the Pi and run it, then hit ctrl+C, the line after the sigwait call that prints "ending wait" is either not executed, or it is executed but does not have access to stdout or it is executed and can access stdout but stdout doesn't print anything to the terminal window. In short. I don't see the message "ending wait" after hitting ctrl+C. I have no idea why! Does anyone have any ideas? Also notice I have some commented out code that has a handler for SIGINT registered using signal and if I uncomment that code and comment out what is currently uncommented then the signal handler for SIGINT does get called when I hit ctrl+C. So, I'm mis-understanding something. Sample is below

Code: Select all

#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

void OnTerm(int sig)
{
    printf("OnTerm %d\n", sig);
}

void OnAbrt(int sig)
{
    printf("OnAbrt %d\n", sig);
}

void OnInt(int sig)
{
    printf("OnInt %d\n", sig);

}

void OnQuit(int sig)
{
    printf("OnQuit %d\n", sig);
}

int main(int argc, char* argv[])
{
    printf("starting\n");
    /*
    signal(SIGTERM, OnTerm);
    signal(SIGABRT, OnAbrt);
    signal(SIGINT, OnInt);
    signal(SIGQUIT, OnQuit);
    printf("signal handlers set\n");
    sleep(5000);
    */

    printf("registering signal handler\n");
    int sigResult = -1;
    sigset_t signal_set;
    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGINT); 
    printf("beginning wait\n");
    sigwait( &signal_set, &sigResult);
    printf("ending wait\n");
    return 0;
}

jahboater
Posts: 5061
Joined: Wed Feb 04, 2015 6:38 pm

Re: sigwait doesn't catch ctrl+c

Tue Aug 21, 2018 6:32 am

Here is a simpler example you could try:-

Code: Select all

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

static void
OnInt( const int sig )
{
  printf( "OnInt %d\n", sig );
}

int
main( void )
{
  struct sigaction actions = { .sa_handler = OnInt, .sa_flags = SA_NODEFER };
  puts("registering signal handler");
  sigaction( SIGINT, &actions, NULL );
  puts("beginning wait");
  sleep(10000);
  puts("ending wait");
}

dsyleixa123
Posts: 583
Joined: Mon Jun 11, 2018 11:22 am

Re: sigwait doesn't catch ctrl+c

Tue Aug 21, 2018 1:16 pm

hello,
I am using this pattern:

Code: Select all

#include <signal.h>     // for catching exit signals

// Signal handler that will be called when Ctrl+C is pressed to stop the program (opt. for additional signals )

void  signal_handler(int signo){
  if(signo == SIGINT){
    // Reset + clean up everything 
    exit(-1);
  }
  // else if(signo == SIGxyz) { ... }
}



int main() {

  signal(SIGINT, signal_handler); // register the exit function for Ctrl+C

}

Last edited by dsyleixa123 on Wed Aug 22, 2018 9:00 am, edited 1 time in total.

jahboater
Posts: 5061
Joined: Wed Feb 04, 2015 6:38 pm

Re: sigwait doesn't catch ctrl+c

Tue Aug 21, 2018 11:57 pm

By the way, signal() is deprecated.
See "man signal" for info.

mikedice417
Posts: 5
Joined: Mon Nov 16, 2015 1:03 am

Re: sigwait doesn't catch ctrl+c

Wed Aug 22, 2018 3:58 am

Yea I switched to using sigaction. It works fine but isn't quite the use case I wanted. Sigaction calls my callback when a signal is available. Therefore if I want to wait for ctrl+C in main and register a callback with sigaction then what is my main function supposed to do while it waits for ctrl+C? I just set it into a loop forever. I think it would have been cleaner to call a blocking system function that would unblock when ctrl+C was pressed because then I wouldn't have needed the blocking while loop. But, as I said it works with sigaction.

Here's the code if you want to see more detail on what I'm doing
https://github.com/mikedice/msgr

jahboater
Posts: 5061
Joined: Wed Feb 04, 2015 6:38 pm

Re: sigwait doesn't catch ctrl+c

Wed Aug 22, 2018 6:57 am

mikedice417 wrote:
Wed Aug 22, 2018 3:58 am
Therefore if I want to wait for ctrl+C in main and register a callback with sigaction then what is my main function supposed to do while it waits for ctrl+C?
Anything you like - call getchar() perhaps since you have a terminal attached.
Do you really need two processes?

Here is another scenario for handling ^C interrupts - common for interactive programs with loops.

Code: Select all

#include <setjmp.h>

static jmp_buf intbuf;

static void
OnInt( const int sig )
{
  longjmp( intbuf, 1 );
}

main()
{
  if( setjmp(intbuf) )
  {
    puts( "^C pressed");
    exit(1); 
  }

  (void)getchar();
}
In the end its just "coding" now you have signals working.

dsyleixa123
Posts: 583
Joined: Mon Jun 11, 2018 11:22 am

Re: sigwait doesn't catch ctrl+c

Wed Aug 22, 2018 7:02 am

jahboater wrote:
Tue Aug 21, 2018 11:57 pm
By the way, signal() is deprecated.
See "man signal" for info.
very regrettable, the signal() function was WAAAY easier to use than the weird sigaction helter-skelter :?

jahboater
Posts: 5061
Joined: Wed Feb 04, 2015 6:38 pm

Re: sigwait doesn't catch ctrl+c

Wed Aug 22, 2018 7:17 am

dsyleixa123 wrote:
Wed Aug 22, 2018 7:02 am
jahboater wrote:
Tue Aug 21, 2018 11:57 pm
By the way, signal() is deprecated.
See "man signal" for info.
very regrettable, the signal() function was WAAAY easier to use than the weird sigaction helter-skelter :?
Yes!
One slight benefit of sigaction is that you don't have to reset the signal handler in the interrupt function.

mikedice417
Posts: 5
Joined: Mon Nov 16, 2015 1:03 am

Re: sigwait doesn't catch ctrl+c

Wed Aug 22, 2018 2:40 pm

jahboater wrote:
Wed Aug 22, 2018 6:57 am
mikedice417 wrote:
Wed Aug 22, 2018 3:58 am
Therefore if I want to wait for ctrl+C in main and register a callback with sigaction then what is my main function supposed to do while it waits for ctrl+C?
Anything you like - call getchar() perhaps since you have a terminal attached.
Do you really need two processes?

No I don't really need two process. Main and listener could be one process. But I had never used fork and signals before so I was trying to learn about those APIs in this project. Hence the excessive processes :). But, I do like the forked process for running the code that handles the incoming connected clients. I like the isolation it gives for each connected client. If something bad goes wrong with one client and their worker process crashes all the other connected clients would be unaffected. Its a nice security/isolation boundary.

n67
Posts: 938
Joined: Mon Oct 30, 2017 4:55 pm

Re: sigwait doesn't catch ctrl+c

Wed Aug 22, 2018 4:03 pm

By the way, the canonical way to wait for a signal is to use pause(2).

man 2 pause
"L'enfer, c'est les autres"

G fytc hsqr rum umpbq rm qyw rm rfc kmbq md rfgq dmpsk:

Epmu Sn!

J lnacjrw njbruh-carppnanm vxm rb mnuncrwp vh yxbcb!

Heater
Posts: 14459
Joined: Tue Jul 17, 2012 3:02 pm

Re: sigwait doesn't catch ctrl+c

Wed Aug 22, 2018 9:04 pm

What kind of brain damage is the pause()?

Quote from the man page:

pause() only returns when a signal was caught and the signal-catching function returned. In this case pause() returns -1, and errno is set to EINTR.


So if pause ever returns the return value is -1. Which is totally redundant information at that time, it's always the same. Might as well not return anything.

And if pause ever returns errno is set to EINTR. Which is totally redundant information at that time, it's always the same.

I guess if you use pause() and the return value is not -1 or the errno is not EINTR then you know your system is totally hosed and it's time to exit()
Memory in C++ is a leaky abstraction .

jahboater
Posts: 5061
Joined: Wed Feb 04, 2015 6:38 pm

Re: sigwait doesn't catch ctrl+c

Thu Aug 23, 2018 7:21 am

Pause can wait forever, unlike sleep.

Return to “C/C++”