Bug 75273

Summary: FBSD 5.3 libpthread (KSE) bug
Product: Base System Reporter: ixew
Component: threadsAssignee: freebsd-threads (Nobody) <threads>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 5.3-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
demo.c
none
demo.mk none

Description ixew 2004-12-19 17:30:26 UTC
sigsuspend() bug

Thread aborts at /usr/src/lib/libpthread/thread/thr_sigsuspend.c line 77 with "oldsigmask is not cleared" when the main thread tries to pthread_cancel() it.

FreeBSD 4.x (libc_r) does not have this problem.

Fix: 

The easy solution :-) remove:
THR_ASSERT(curthread->oldsigmask == NULL, "oldsigmask is not cleared");
Comment 1 Daniel Eischen freebsd_committer freebsd_triage 2004-12-19 17:54:54 UTC
On Sun, 19 Dec 2004, Enoch W. wrote:

> >Description:
> sigsuspend() bug
>
> Thread aborts at /usr/src/lib/libpthread/thread/thr_sigsuspend.c line 77 with "oldsigmask is not cleared" when the main thread tries to pthread_cancel() it.
>
> FreeBSD 4.x (libc_r) does not have this problem.
>
> >How-To-Repeat:
>
> >Fix:
> The easy solution :-) remove:
> THR_ASSERT(curthread->oldsigmask == NULL, "oldsigmask is not cleared");

Sample program to demonstrate the problem, please?

This could be fixed in -current, but since I don't know how to repeat the
problem, I can't test it.
Comment 2 Craig Rodrigues 2004-12-22 06:05:04 UTC
Here is the non-MIME mangled version of the demo source.
It works for me on -CURRENT.



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
 
#define ASSRET(cond) do { \
   if (!(cond)) { \
     fprintf(stderr,  "ASSRET ERROR @ %d -> %s\n", __LINE__, \
 	    strerror(ret == -1 ? errno : ret)); \
    exit(EXIT_FAILURE); \
  } \
} while (0)

int tock;

void tick()
{
  tock = 1;
}

void *pulse(void *arg)
{
  int ret;
  struct itimerval it;
  sigset_t set;

  sigemptyset(&set);
  sigaddset(&set, SIGALRM);
  ret = sigprocmask(SIG_BLOCK, &set, NULL);
  ASSRET(ret == 0);
  sigemptyset(&set);

  it.it_interval.tv_sec = 1;
  it.it_interval.tv_usec = 0;
  it.it_value.tv_sec = 1;
  it.it_value.tv_usec = 0;
  ret = setitimer(ITIMER_REAL, &it, NULL);
  ASSRET(ret == 0);

  while (1) {
    while (!tock)
      sigsuspend(&set);
    tock = 0;
    putchar('*');
    fflush(stdout);
  }
}

int main()
{
  int ret;
  pthread_attr_t attr;
  pthread_t thread;

  ret = pthread_attr_init(&attr);
  ASSRET(ret == 0);
  ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  ASSRET(ret == 0);

  signal(SIGALRM, tick);

  ret = pthread_create(&thread, NULL, pulse, NULL);
  ASSRET(ret == 0);

  printf("Press Enter to cancel the pulse() thread\n");
  while (getchar() != '\n');

  ret = pthread_cancel(thread);
  ASSRET(ret == 0);
  ret = pthread_join(thread, NULL);
  ASSRET(ret == 0);

  printf("Press Enter to end\n");
  while (getchar() != '\n');
  return 0;
}
Comment 3 Craig Rodrigues 2004-12-22 18:18:52 UTC
On Wed, Dec 22, 2004 at 06:10:24AM +0000, Craig Rodrigues wrote:
>  Here is the non-MIME mangled version of the demo source.
>  It works for me on -CURRENT.

While this testcase does not fail on -CURRENT, I just verified that it does in
fact fail on 5.3 with:
Press Enter to cancel the pulse() thread
******
Fatal error 'oldsigmask is not cleared' at line 77 in file /usr/src/lib/libpthread/thread/thr_sigsuspend.c (errno = 4)
Abort trap (core dumped)

-- 
Craig Rodrigues        
rodrigc@crodrigues.org
Comment 4 Jilles Tjoelker freebsd_committer freebsd_triage 2010-05-02 22:25:36 UTC
State Changed
From-To: open->closed

This was fixed before 6.0 in r139052. I cannot reproduce it on 7.x 
(libthr/libkse), 8.x and 9.x either.