Received: from SOUTH-STATION-ANNEX.MIT.EDU by po7.MIT.EDU (5.61/4.7) id AA20217; Tue, 12 Dec 95 10:05:51 EST
Received: from beech.soton.ac.uk by MIT.EDU with SMTP
	id AA08199; Tue, 12 Dec 95 10:01:47 EST
Received: from bright.ecs.soton.ac.uk (bright.ecs.soton.ac.uk [152.78.64.201])
   by beech.soton.ac.uk (8.6.12/hub-8.5a) with SMTP id PAA14713
   for <pthreads-bugs%mit.edu@relay.soton.ac.uk>; Tue, 12 Dec 1995 15:01:28 GMT
Received: from whirligig.ecs.soton.ac.uk by bright.ecs.soton.ac.uk; Tue, 12 Dec 95 15:02:44 GMT
From: David Wragg <dpw93@ecs.soton.ac.uk>
Received: from cally.ecs.soton.ac.uk..ecs.soton.ac.uk by whirligig.ecs.soton.ac.uk; Tue, 12 Dec 95 15:02:41 GMT
Message-Id: <12083.199512121502@cally.ecs.soton.ac.uk..ecs.soton.ac.uk>
Subject: PThreads signal bug
To: pthreads-bugs@MIT.EDU
Date: Tue, 12 Dec 1995 15:02:50 +0000 (GMT)
X-Mailer: ELM [version 2.4 PL24]
Content-Type: text
Content-Length: 2104      

Hi,
 
I have found a serious bug in your pthreads package (version
1.60.beta4). It occurs when a thread receives the same signal multiple
times in quick succession.
 
The problem is this: If a thread recieves a signal, then recieves the
same signal before it can handle it, then the sigcount member of the
pthread structure will be greater than the number of signals shown in
the sigpending member.

This causes problems in pthread_{sched_other|resched|sched}_resume,
because they will loop until pthread_run->sigcount == 0. But as
signals are processed by examining the pthread_run->sigpending,
infinite loops occur.

Here's a program which will get into such a loop:
 
============================================================

/* Program to expose signal bug */
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
 
pthread_t main_thread;

void *thread_proc(void *junk)
{
  u_int i;

  sleep(2);

  fprintf(stderr, "Sending a burst of signals to the main thread\n");

  for(i = 0; i < 5; i++)
    pthread_kill(main_thread, SIGCHLD);

  fprintf(stderr, "Sent signals\n");
  return NULL;
}


int main(void)
{
  pthread_t thr;

  pthread_init();
  main_thread = pthread_self();

  pthread_create(&thr, NULL, thread_proc, NULL);
  fprintf(stderr, "Started the thread\n");

  sleep(5);
  fprintf(stderr, "If you see this, we didn't expose the bug\n");
  return 0;
}

======================================================================

If you run this program in a debugger, with a breakpoint on
pthread_sig_process(), you will see that pthread_run->sigpending and
pthread_run->sigcount are inconsistent.


The quick fix I made was this: In sig.c and pthread_kill.c there are
groups of lines like:

  sigaddset(&(pthread->sigpending), sig);
  pthread->sigcount++;          

They may not be consecutive, they may not be in that order, pthread
may actually be pthread_run, etc.
 
My modification went:

  if (!sigismember(&(pthread->sigpending), sig)) {
      sigaddset(&(pthread->sigpending), sig);
      pthread->sigcount++;          
  }

It seems to work.

Dave Wragg.
