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

#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;
}
-- 
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

Reply via email to