bug#14569: 24.3.50; bootstrap fails on Cygwin

Ken Brown kbrown@cornell.edu
Sun Jun 16 13:12:00 GMT 2013


[Adding the bug address back to the CC so that this gets archived.]

On 6/15/2013 9:54 AM, Angelo Graziosi wrote:
> Christopher Faylor wrote
>>> On 06/14/2013 11:03 AM, Christopher Faylor wrote:
>>>> You pointed to an archived mail messages which implies that was fixed
>>>> more than a year ago.  What makes you think it is still a problem?
>>>
>>> The message I pointed to
>>> <http://cygwin.com/ml/cygwin/2012-05/msg00472.html> says this:
>>>
>>>> Testcase signal/kill: Signals may or may not reach the correct thread
>>>> with 1.7.12-1 and newer.
>>>
>>> Confirmed.  I think the reason is that we only have a single event to
>>> signal that a POSIX signal arrived instead of a per-thread event, but
>>> I'm not sure.  This is cgf's domain so I leave it at that for now.
>>>
>>> I interpreted this to mean "the existence of the bug is confirmed,
>>> here's why the bug occurs, and I'll let cgf deal with it".  I didn't
>>> see any followup message where cgf (is that you?) dealt with it.  My
>>> apologies if I misinterpreted the email.
>>
>> Oops.  I didn't read Corinna's message as thoroughly as I should have.
>> Sorry.
>>
>> That particular issue was supposed to have been fixed in Cygwin 1.7.17,
>> released in October 2012.
>
> Out of curiosity, I tried the test cases I found in that thread, more
> precisely here:
>
>    http://cygwin.com/ml/cygwin/2012-05/msg00434.html
>
>
> and the results are:
>
> $ gcc otto_test1.c -o otto_test1
> $ ./otto_test1
> Testing deferred pthread_cancel()
>
> Thread 0 starting (0x200102c0)
> Thread 1 starting (0x20010360)
> Thread 2 starting (0x20010400)
>
> Cancelling thread 2 (0x20010400)
> Thread 2 exiting (0x20010400)
> Cancelling thread 1 (0x20010360)
> Thread 1 exiting (0x20010360)
> Cancelling thread 0 (0x200102c0)
> Thread 0 exiting (0x200102c0)
>
> Thread 0 is gone (0x200102c0)
> Thread 1 is gone (0x20010360)
> Thread 2 is gone (0x20010400)
>
> $ gcc otto_test2.c -o otto_test2
> $ ./otto_test2
> Testing asynchronous pthread_cancel()
>
> Thread 0 starting (0x200102c0)
> Changing canceltype from 0 to 1
> Thread 1 starting (0x20010360)
> Changing canceltype from 0 to 1
> Thread 2 starting (0x20010400)
> Changing canceltype from 0 to 1
>
> Cancelling thread 2 (0x20010400)
> Thread 2 exiting (0x20010400)
> Cancelling thread 1 (0x20010360)
> Thread 1 exiting (0x20010360)
> Cancelling thread 0 (0x200102c0)
> Thread 0 exiting (0x200102c0)
>
> Thread 0 is gone (0x200102c0)
> Thread 1 is gone (0x20010360)
> Thread 2 is gone (0x20010400)
>
> $ gcc otto_test3.c -o otto_test3
> $ ./otto_test3
> Testing pthread_kill()
>
> Thread 0 starting (0x200102c0)
> Thread 1 starting (0x20010360)
> Thread 2 starting (0x20010400)
>
> Sending SIGUSR1 to thread 2 (0x20010400)
> Thread 2 executes signal handler (0x20010400)
> Thread 2 encountered an error: Interrupted system call (0x20010400)
> Sending SIGUSR1 to thread 1 (0x20010360)
> Thread 1 executes signal handler (0x20010360)
> Thread 1 encountered an error: Interrupted system call (0x20010360)
> Sending SIGUSR1 to thread 0 (0x200102c0)
> Thread 0 executes signal handler (0x200102c0)
> Thread 0 encountered an error: Interrupted system call (0x200102c0)
>
> Are the errors in the last test case to be expected under the 20130612
> snapshot (CYGWIN_NT-5.1, 1.7.21s 20130612 21:06:59, i686 Cygwin)?

I can replicate this on my system, consistently.  There's clearly a 
problem, but it's not the same as in the original Cygwin bug report.  In 
the present case, the signal is received by the right thread, but 
something goes wrong afterwards.

I'm attaching the test case for ease of reference.

Ken
-------------- next part --------------
/* http://cygwin.com/ml/cygwin/2012-05/msg00434.html */

#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

pthread_t tids[3];
sem_t semaphore;

static void cleanup_handler(void *arg) {
  int *intptr = (int*)arg;
  pthread_t self = pthread_self();
  fprintf(stderr, "Thread %i exiting (%p)\n", *intptr, self);
}

static void* simplethread(void *arg) {
  int *intptr = (int*)arg;
  pthread_t self = pthread_self();
  fprintf(stderr, "Thread %i starting (%p)\n", *intptr, self);

  pthread_cleanup_push(&cleanup_handler, intptr);

  while (1) {
    if (sem_wait(&semaphore) != 0) {
      fprintf(stderr, "Thread %i encountered an error: %s (%p)\n",
          *intptr, strerror(errno), self);
    } else {
      fprintf(stderr, "Thread %i woke up just fine\n", *intptr);
    }
  }

  pthread_cleanup_pop(1);
  return NULL;
}

static void sigusr1_handler(int signal __attribute((unused))) {
  pthread_t self = pthread_self();
  int tnum = 0;
  while (tnum < 3) {
    if (tids[tnum] == self) {
      break;
    }
    tnum++;
  }

  fprintf(stderr, "Thread %i executes signal handler (%p)\n", tnum, self);
}

static void install_handler(void) {
  struct sigaction act;
  act.sa_handler = &sigusr1_handler;
  sigemptyset(&(act.sa_mask));
  act.sa_flags = 0;

  if (sigaction(SIGUSR1, &act, NULL) != 0) {
    fprintf(stderr, "Can't set signal handler: %s\n", strerror(errno));
    exit(1);
  }

  sigset_t sset;
  sigemptyset(&sset);
  sigaddset(&sset, SIGUSR1);
  if (sigprocmask(SIG_UNBLOCK, &sset, NULL) != 0) {
    fprintf(stderr, "Can't unblock SIGUSR1: %s\n", strerror(errno));
  }
}

int main() {
  fprintf(stderr, "Testing pthread_kill()\n\n");

  int i;
  int result;

  sem_init(&semaphore, 0, 0);
  install_handler();

  for (i=0; i<3; i++) {
    int *intptr = (int*)malloc(sizeof(int));
    *intptr = i;
    result = pthread_create(tids+i, NULL, &simplethread, intptr);
    if (result != 0) {
      fprintf(stderr, "Can't create thread: %s\n", strerror(result));
      return 1;
    }
  }

  sleep(1);
  install_handler();
  fprintf(stderr, "\n");

  int mainint = 42;
  pthread_cleanup_push(&cleanup_handler, &mainint);

  for (i=2; i>=0; i--) {
    fprintf(stderr, "Sending SIGUSR1 to thread %i (%p)\n", i, tids[i]);
    result = pthread_kill(tids[i], SIGUSR1);
    if (result != 0) {
      fprintf(stderr, "Error during pthread_kill: %s\n", strerror(result));
    }
    sleep(1);
  }

  pthread_cleanup_pop(0);
  return 0;
}
-------------- next part --------------
--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


More information about the Cygwin mailing list