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