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

// 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;
}
-- 
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