2

Currently I am programming a shell and I use the waitpid() function for my children processes.

I also installed a signal handler so I can trap the SIGINT (CTRL+C) signal.

So what I want now is when someone presses the SIGINT (CTRL+C) signal it should leave the waitpid() functions and keep going as usually.

I am looking for a function who can help me about that.

Acorn
  • 24,970
  • 5
  • 40
  • 69
Nado Ba
  • 21
  • 1

2 Answers2

0

Install your signal handler without the SA_RESTART flag:

void handler( int sig, siginfo_t *si, void *arg )
{
    ...
}

...

struct sigaction newact;
memset( &newact, 0, sizeof( newact ) );
sigemptyset( &newact.sa_mask );
newact.sa_flags = SA_SIGINFO;  // note that **lack** of SA_RESTART
newact.sa_siginfo = handler;

sigaction( SIGINT, &newact, NULL );

You'll have to add error checking to that, and note that you will now have to handle interrupted calls in your code.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • 1
    OT: I'd use `struct sigaction newact = {0};` instead of calling `memset()`. – alk May 19 '18 at 13:40
  • @alk I've been around too long... :-) – Andrew Henle May 19 '18 at 13:41
  • Also I doubt that explicitly emptying `sa_mask` is necessary. Also^2 why do you set `SA_SIGINFO` for a handler which actually does nothing. So assuming `void handler(int sig);` then the short version could be `{ sigaction(SIGINT, (struct sigaction){handler}, NULL); }` :-) – alk May 19 '18 at 13:44
  • Thanks for your help, but I dont understand what you calling, do you have a reference or something like that? – Nado Ba May 19 '18 at 13:45
  • @alk I tend to be paranoid about making sure all my variables are properly initialized - a defensive coding measure against the bugs I'm going to put in (two kinds of programmers: those who create bugs, and liars). As far as `SA_SIGINFO`, we don't know what he OP's signal handler does, so I provided an example of the more complex usage. – Andrew Henle May 19 '18 at 13:49
0

A process blocking on waitpid() would return on reception of a signal and set errno to EINTR.

For this to work the signal handler my not have been installed with the option SA_RESTART.

To install a signal handle without setting the option SA_RESTART the prefered function is sigaction().

void handle(int sig)
{
  /* Do nothing. */
}

int main(void)
{
  sigaction(SIGINT, (struct sigaction){handler}, NULL);

  /* fork and bla ... */

  if (-1 == waitpid(..., /*no WNOHANG here */))
  {
    if (EINTR == errno)
    {
      /* process received signal */
      ...
alk
  • 69,737
  • 10
  • 105
  • 255