cygwin 3.6.0: Signals may fail permanently if received after SIGSTOP

Christian Franke Christian.Franke@t-online.de
Wed Mar 5 10:23:26 GMT 2025


Takashi Yano via Cygwin wrote:
> On Mon, 24 Feb 2025 11:29:59 +0100
> Christian Franke wrote:
>> Found with 'stress-ng --cpu-sched 1':
>>
>> Testcase (attached):
>>
>> $ uname -r
>> 3.6.0-0.387.g8cebbb2b42bf.x86_64
>>
>> $ gcc -o timersig timersig.c
>>
>> $ ./timersig
>> 638: fork()=639
>> !!!!!!!!!!!!!...!!!!!!!!!!!!!SIGSTOP: Permission denied
>>       0 [itimer] timersig 639 sig_send: error sending signal 14, pid 639,
>> pipe handle 0x14C, nb 0, packsize 192, Win32 error 0
>> SIGKILL: Permission denied
>>
>> $ kill 639
>> -bash: kill: (639) - Permission denied
>>
>> $ kill -9 639
>> -bash: kill: (639) - Permission denied
>>
>> $ /bin/kill --force 639
>>
>> $ /bin/kill --force 639
>> kill: 639: No such process
>>
>>
>> A similar problem, but without the "error sending signal" message,
>> occurs if the timer is not used but the parent process issues SIGSTOP
>> SIGALRM SIGCONT ... sequences.
> Thanks for the report, especially for the test case. I was able to
> easily reproduce the issue. However, I haven't found the cause until
> today. I spent 3 days investigating and discovered three bugs that
> prevent the test case from behaving as expected.
>
> I'll submit the patch seriese shotly.

Testcase works as expected with 3.6.0-0.419.g3c1308ed890e.x86_64, thanks!


Unfortunately signals may be lost, a new testcase is attached:

$ uname -r
3.6.0-0.419.g3c1308ed890e.x86_64

$ gcc -o lostsig lostsig.c

$ ./lostsig
1157: fork()=1158
SIGALRM x 10
[ALRM]
[ALRM]
[ALRM]
SIGSTOP
[ALRM]
SIGTERM
SIGCONT
waitpid()...
[TERM]
1158: 4 SIGALRM received, exit(42)
waidpid()=1158, status=0x2a00

$ ./lostsig
1163: fork()=1164
SIGALRM x 10
SIGSTOP
SIGTERM
SIGCONT
waitpid()...
[ALRM]
[TERM]
...hangs...


A 'ps' is a second terminal then shows that the child process is still 
in S)topped state. 'kill -CONT ...' works to continue.

If the testcase is assigned to a single core with 'taskset 0x1 ...', it 
apparently always hangs.

-- 
Regards,
Christian

-------------- next part --------------
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

static volatile sig_atomic_t sigcnt, term;

static void sighandler1(int sig)
{
  (void)sig;
  ++sigcnt;
  write(1, "[ALRM]\n", 7);
}

static void sighandler2(int sig)
{
  (void)sig;
  term = 1;
  write(1, "[TERM]\n", 7);
}

int main()
{
  pid_t pid = fork();
  if (pid == (pid_t)-1) {
    perror("fork"); return 1;
  }

  if (!pid) {
    signal(SIGALRM, sighandler1);
    signal(SIGTERM, sighandler2);

    while (!term)
      sched_yield();

    printf("%d: %d SIGALRM received, exit(42)\n", (int)getpid(), sigcnt);
    fflush(stdout);
    _exit(42);
  }

  printf("%d: fork()=%d\n", (int)getpid(), (int)pid);
  sleep(1);

  const int n = 10;
  printf("SIGALRM x %d\n", n); fflush(stdout);
  for (int i = 0; i < n; i++) {
    sched_yield();
    if (kill(pid, SIGALRM))
      perror("SIGALRM");
  }

  printf("SIGSTOP\n"); fflush(stdout);
  if (kill(pid, SIGSTOP))
    perror("SIGSTOP");
  printf("SIGTERM\n"); fflush(stdout);
  if (kill(pid, SIGTERM))
      perror("SIGTERM");
  printf("SIGCONT\n"); fflush(stdout);
  if (kill(pid, SIGCONT))
    perror("SIGCONT");

  printf("waitpid()...\n"); fflush(stdout);
  int status = -1;
  int wp = waitpid(pid, &status, 0);
  printf("waidpid()=%d, status=0x%04x\n", wp, status);
  return 0;
}


More information about the Cygwin mailing list