cygwin 3.6.0: No signals received after swapcontext() is used

Christian Franke Christian.Franke@t-online.de
Thu Mar 6 12:24:27 GMT 2025


Found because 'stress-ng --context 1 ...' always hangs.
The attached testcase uses the example from Linux swapcontext(3) to call 
the context functions.
$ uname -r
3.6.0-0.419.g3c1308ed890e.x86_64
$ gcc -o ctxnosig ctxnosig.c
$ ./ctxnosig # ... and hit ^C
waste_time: started
[^C][SIGINT]
waste_time: returning, sigflag=1
main2: swapcontext(&uctx_main, &uctx_func2)
func2: started
func2: swapcontext(&uctx_func2, &uctx_func1)
func1: started
func1: swapcontext(&uctx_func1, &uctx_func2)
func2: returning
func1: returning
main2: exiting
waste_time: started
[^C][^C][^C][^C][^C][^C][^C][^C][^C][^C]...
waste_time: returning, sigflag=0
main: sleep(5)...
[SIGINT]
[SIGINT]
[^C][SIGINT]
main: sleep(5)=2
main: exiting, 4 SIGINT received
Possibly a minor issue because these functions are obsoleted (last seen 
in POSIX 2004), but at least cygruby*.dll import these:
$ objdump -p /bin/cygruby320.dll | grep context
         00378ca8  <none>  0286  getcontext
         00378e08  <none>  0391  makecontext
         003791c0  <none>  05cd  swapcontext
...
-- 
Regards,
Christian
-------------- next part --------------
// BEGIN: example from Linux swapcontext(3)
#include <ucontext.h>
#include <stdio.h>
#include <stdlib.h>
static ucontext_t uctx_main, uctx_func1, uctx_func2;
#define handle_error(msg) \
 do { perror(msg); exit(EXIT_FAILURE); } while (0)
static void
func1(void)
{
 printf("func1: started\n");
 printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n");
 if (swapcontext(&uctx_func1, &uctx_func2) == -1)
 handle_error("swapcontext");
 printf("func1: returning\n");
}
static void
func2(void)
{
 printf("func2: started\n");
 printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n");
 if (swapcontext(&uctx_func2, &uctx_func1) == -1)
 handle_error("swapcontext");
 printf("func2: returning\n");
}
static void
main2(int argc, char *argv[])
{
 char func1_stack[16384];
 char func2_stack[16384];
 if (getcontext(&uctx_func1) == -1)
 handle_error("getcontext");
 uctx_func1.uc_stack.ss_sp = func1_stack;
 uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
 uctx_func1.uc_link = &uctx_main;
 makecontext(&uctx_func1, func1, 0);
 if (getcontext(&uctx_func2) == -1)
 handle_error("getcontext");
 uctx_func2.uc_stack.ss_sp = func2_stack;
 uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
 /* Successor context is f1(), unless argc > 1 */
 uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
 makecontext(&uctx_func2, func2, 0);
 printf("main2: swapcontext(&uctx_main, &uctx_func2)\n");
 if (swapcontext(&uctx_main, &uctx_func2) == -1)
 handle_error("swapcontext");
 printf("main2: exiting\n");
}
// END: example from Linux swapcontext(3)
//////////////////////////////////////////////////////////
#include <math.h>
#include <signal.h>
#include <unistd.h>
static volatile sig_atomic_t sigcnt, sigflag;
static void sighandler(int sig)
{
 (void)sig;
 ++sigcnt;
 sigflag = 1;
 write(1, "[SIGINT]\n", 9);
}
static void waste_time()
{
 printf("waste_time: started\n");
 int flag = 0;
 sigflag = 0;
 volatile double x = 1.0;
 const int n = 100*1000*1000; // ~5s on i7-14700
 for (int i = 0; i < n && !flag; i++) {
 x = asin(sin(x));
 flag = sigflag;
 }
 printf("waste_time: returning, sigflag=%d\n", flag);
}
int main(int argc, char *argv[])
{
 signal(SIGINT, sighandler);
 waste_time(); // signals received
 main2(argc, argv); // swapcontext example
 waste_time(); // no signals received
 printf("main: sleep(5)...\n");
 printf("main: sleep(5)=%u\n", sleep(5)); // aborted by (new) signal (only)
 printf("main: exiting, %d SIGINT received\n", sigcnt);
 return 0;
}


More information about the Cygwin mailing list

AltStyle によって変換されたページ (->オリジナル) /