This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: 1.7.15-1: pthread_cancel and pthread_kill not working as expected


> Would you mind to provide *simple* testcases to allow easy debugging
> of your observations?

I reduced the various tests to three rather simple individual testcases
because those show possibly different bugs.

Testcase cancel deferred:
Works with 1.7.9 and 20120517 snapshot, fails (hangs) with 1.7.12-1
and 1.7.15-1.

Testcase cancel asynchronous:
Async cancel seems to have no effect with any tested version.

Testcase signal/kill:
Signals may or may not reach the correct thread with 1.7.12-1 and newer.

Otto
#include <errno.h>
#include <pthread.h>
#include <semaphore.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;
}

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

  int i;
  int result;

  sem_init(&semaphore, 0, 0);

  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);
  fprintf(stderr, "\n");

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

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

  fprintf(stderr, "\n");
  for (i=0; i<3; i++) {
    result = pthread_kill(tids[i], 0);
    if (result == 0) {
      fprintf(stderr, "Thread %i is still there (%p)\n", i, tids[i]);
    } else {
      fprintf(stderr, "Thread %i is gone (%p)\n", i, tids[i]);
    }
  }

  pthread_cleanup_pop(0);
  return 0;
}
#include <errno.h>
#include <pthread.h>
#include <semaphore.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);

  int oldtype;
  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
  fprintf(stderr, "Changing canceltype from %i to %i\n", oldtype, PTHREAD_CANCEL_ASYNCHRONOUS);

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

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

  int i;
  int result;

  sem_init(&semaphore, 0, 0);

  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);
  fprintf(stderr, "\n");

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

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

  fprintf(stderr, "\n");
  for (i=0; i<3; i++) {
    result = pthread_kill(tids[i], 0);
    if (result == 0) {
      fprintf(stderr, "Thread %i is still there (%p)\n", i, tids[i]);
    } else {
      fprintf(stderr, "Thread %i is gone (%p)\n", i, tids[i]);
    }
  }

  pthread_cleanup_pop(0);
  return 0;
}
#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;
}

--
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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]