[PATCH] Cygwin: signa: Redesign signal queue handling
Christian Franke
Christian.Franke@t-online.de
Fri Mar 7 16:35:23 GMT 2025
Christian Franke wrote:
> Takashi Yano wrote:
>> The previous implementation of the signal queue behaves as:
>> 1) Signals in the queue are processed in a disordered manner.
>> 2) If the same signal is already in the queue, new signal is discarded.
>>
>> Strictly speaking, these behaviours do not violate POSIX. However,
>> these could be a cause of unexpected behaviour in some software. In
>> Linux, some important signals such as SIGSTOP/SIGCONT do not seem to
>> behave like that.
>>
>> With this patch prevents all signals from that issues by redesigning
>> the signal queue, Only the exception is the case that the process is
>> in the PID_STOPPED state. In this case, SIGCONT/SIGKILL should be
>> processed prior to the other signals in the queue.
>>
>> Addresses:https://cygwin.com/pipermail/cygwin/2025-March/257582.html
>> ...
>
> A quick test with many runs of 'lostsig' testcase with or without
> 'taskset 0x1' no longer shows any problems. No SIGALRM were lost (not
> required), [SIGTERM] is always printed after all [SIGALRM] (not
> required), SIGCONT is never lost. The previous 'timersig' testcase
> also still succeeds.
>
>
Unfortunately with another testcase (attached) without SIGSTOP/CONT but
two different signals sent in a loop it does not work:
$ ./swapsigs
remaining 5
1891: fork()=1892
SIGALRM 0
remaining 4
SIGTERM 0
SIGALRM 1
SIGTERM 1
SIGALRM 2
[ALRM]
SIGTERM 2
SIGALRM 3
SIGTERM 3
SIGALRM 4
[TERM]
SIGTERM 4
[ALRM]
SIGALRM 5
SIGTERM 5
SIGALRM 6
SIGTERM 6
[TERM]
[ALRM]
SIGALRM 7
... both processes hang ...
Could not be reproduced with 'taskset 0x1' or with original
3.6.0-0.423.ga3863bfeb73f.x86_64.
--
Regards,
Christian
-------------- next part --------------
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>
static volatile sig_atomic_t sigcnt1, sigcnt2;
static void sighandler1(int sig)
{
(void)sig;
++sigcnt1;
write(1, "[ALRM]\n", 7);
}
static void sighandler2(int sig)
{
(void)sig;
++sigcnt2;
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);
time_t start = time(NULL), t = 5;
do {
printf("remaining %d\n", t); fflush(stdout);
sleep(1);
t -= time(NULL) - start;
} while (t > 0);
printf("%d: %d SIGALRM %d SIGTERM received, exit(42)\n",
(int)getpid(), sigcnt1, sigcnt2);
fflush(stdout);
_exit(42);
}
printf("%d: fork()=%d\n", (int)getpid(), (int)pid);
sleep(1);
const int n = 10;
for (int i = 0; i < n; i++) {
const union sigval sv = {0};
printf("SIGALRM %d\n", i); fflush(stdout);
if (sigqueue(pid, SIGALRM, sv))
perror("SIGALRM");
printf("SIGTERM %d\n", i); fflush(stdout);
if (sigqueue(pid, SIGTERM, sv))
perror("SIGTERM");
}
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-patches
mailing list