# discuss@charon.mit.edu: [155] in "Pthreads Bugs"

# [155] in Pthreads Bugs

## pthread_kill() Bug

### daemon@ATHENA.MIT.EDU (Thu Dec 26 20:34:45 1996 )

    From: Chris Colohan <colohan@eecg.toronto.edu>
    To: pthreads-bugs@MIT.EDU, proven@MIT.EDU
    Date: 	Thu, 26 Dec 1996 20:33:48 -0500

    pthread_kill() has a problem in PThreads 1.60beta6.  It checks to see
    if the target thread is in the state PS_SIGWAIT, and if it is it
    reschedules it.  But it does not check if there is more than one
    thread in the PS_SIGWAIT state, and hence mangles the pthread_sigwait
    linked list, potentially resulting in threads getting blocked forever,
    and signals never being delivered.  I have a *very* contrived test
    case that demonstrates this problem if you would like it.  Please let
    me know...

    Chris
    ===

    Diffs created with diff -c:

    *** /home/colohan/thesis/t/pthreads-1_60_beta6/pthreads/pthread_kill.c	Tue Feb 21 03:07:18 1995
    --- pthread_kill.c	Thu Dec 26 19:50:22 1996
    ***************
    *** 41,51 ****
    --- 41,58 ----

      #include <pthread.h>

    + /* Defined in sig.c, a linked list of threads currently
    +  * blocked in sigwait(): */
    + extern struct pthread * pthread_sigwait;
    +
    +
      /* ==========================================================================
       * pthread_kill()
       */
      int pthread_kill(struct pthread * pthread, int sig)
      {
    + 	struct pthread ** pthread_ptr;
    +
      	pthread_sched_prevent();

      	/* Check who is the current owner of pthread */
    ***************
    *** 53,62 ****
      	if (0) {
      	} else {
      		if (pthread->state == PS_SIGWAIT) {
    ! 			if (sigismember(pthread->data.sigwait, sig)) {
    ! 				*(int *)(pthread->ret) = sig;
    ! 				pthread_sched_other_resume(pthread);
    ! 				return(OK);
      			}
      		}
      		sigaddset(&(pthread->sigpending), sig);
    --- 60,84 ----
      	if (0) {
      	} else {
      		if (pthread->state == PS_SIGWAIT) {
    ! 			if(sigismember(pthread->data.sigwait, sig)) {
    ! 			    for (pthread_ptr = &pthread_sigwait;
    ! 				 (*pthread_ptr);
    ! 				 pthread_ptr = &((*pthread_ptr)->next)) {
    ! 				if ((*pthread_ptr) == pthread) {
    !
    ! 				    /* Take the thread out of the
    ! 				     * pthread_sigwait linked list: */
    ! 				    *pthread_ptr=(*pthread_ptr)->next;
    !
    ! 				    *(int *)(pthread->ret) = sig;
    ! 				    pthread_sched_other_resume(pthread);
    ! 				    return(OK);
    ! 				}
    ! 			    }
    ! 			    /* A thread should not be in the state PS_SIGWAIT
    ! 			     * without being in the pthread_sigwait linked
    ! 			     * list: */
    ! 			    PANIC();
      			}
      		}
      		sigaddset(&(pthread->sigpending), sig);