1

sigsuspend is a function that changes the mask and suspends the process until a new signal is delivered, but what surprised me is that the pending signals are being delivered also after the sigsuspend.

For example: while the process is sleeping (5 sec), a ctrl-z will not execute the SIGTSTP handler because it's masked, but after the sigsuspend the signal is received automatically so the sigsuspend executes the pending signal handler also, it's right? `

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

void handlerSIGTSTP()
{
    printf("I have recieved the signal \n");
}

int main()
{
    
    sigset_t mask;
    sigset_t ancien;
    signal(SIGTSTP,handlerSIGTSTP);
    sigaddset(&mask,SIGTSTP);
    sigprocmask(SIG_SETMASK,&mask,&ancien);
    printf("J'entre en sleep\n");
    sleep(5);
    printf("J'entre en suspend\n");
    sigsuspend(&ancien);    
}

Execution:

J'entre en sleep
^ZJ'entre en suspend
J'ai recu le signal maintenant
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
SBAT
  • 49
  • 5
  • Note that `sigsuspend()` affects a thread rather than a process, though if the process is single-threaded as yours is, the difference is mostly moot. As `sigsuspend()` returns, the blocking of the signal(s) is no longer in effect, and the pending signals are delivered before it returns to the user code. You could add another print operation after `sigsuspend()` to show the sequencing. – Jonathan Leffler Nov 16 '22 at 16:30
  • 3
    Note that you should not call `printf()` in a signal handler — see [How to avoid using `printf()` in a signal handler?](https://stackoverflow.com/q/16891019/15168) for most of the sordid details. – Jonathan Leffler Nov 16 '22 at 16:31
  • 1
    You have UB. `mask` is on the stack so it is not initialized. You need `sigemptyset` to clear it. – Craig Estey Nov 16 '22 at 16:39
  • 1
    Even if `mask` were allocated statically, the docs say that it must be initialized via `sigemptyset()` or `sigfillset()` before being passed to any of the other `sigset_t` manipulation functions. – John Bollinger Nov 16 '22 at 17:01

1 Answers1

3

Although your example code has some issues that are addressed in comments, I'll focus in this answer on the main questions you raise, which are not fundamentally dependent on the example program.

sigsuspend is a function that changes the mask and suspends the process until a new signal is delivered,

Your use of the word "new" in that description suggests a misunderstanding. The docs do not use it, and it doesn't really make sense in context.

but what surprised me is that the pending signals are being delivered also after the sigsuspend.

Yes. sigsuspend() temporarily replaces the signal mask and suspends execution until a signal is delivered whose action is to invoke a signal handler or terminate the process. That can be a signal that was already pending before sigsuspend() was called. That is one of the circumstances that the idiomatic combination of sigprocmask() with sigsuspend() is specifically aimed at handling. This allows a process to avoid handling an expected signal before it is ready for it.

For example: while the process is sleeping (5 sec), a ctrl-z will not execute the SIGTSTP handler because it's masked, but after the sigsuspend the signal is received automatically so the sigsuspend executes the pending signal handler also, it's right?

Yes. In your example code, sigsuspend() unblocks SIGTSTP, so if there is a pending SIGTSTP then it is delivered within the scope of the sigsuspend(). That triggers a signal handler in your case, so when the handler returns, sigsuspend() terminates.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Thank you for the answer! so we can take advantage of the combination of sigprocmask with sigsuspend to make a communication between between parent and child processes for exemple in the child process we sends a signal to the parent and we suspend the process with sigsuspend and the parent will receive the signal and resend another signal to the child to let him continue – SBAT Nov 16 '22 at 18:46
  • Yes, @SBAT. To avoid a race condition, the parent would block the expected signal before before launching the child. That prevents the signal being delivered to it before it calls `sigsuspend()` to receive it. – John Bollinger Nov 16 '22 at 18:59