[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

r3126 - in glibc-package/trunk/debian: . patches patches/any



Author: aurel32
Date: 2008-09-09 14:12:12 +0000 (Tue, 09 Sep 2008)
New Revision: 3126

Added:
   glibc-package/trunk/debian/patches/any/cvs-timer_delete.diff
Modified:
   glibc-package/trunk/debian/changelog
   glibc-package/trunk/debian/patches/series
Log:
  * any/cvs-timer_delete.diff: new patch from upstream to fix a thread race
    in glibc timer_delete.



Modified: glibc-package/trunk/debian/changelog
===================================================================
--- glibc-package/trunk/debian/changelog	2008-09-09 13:56:06 UTC (rev 3125)
+++ glibc-package/trunk/debian/changelog	2008-09-09 14:12:12 UTC (rev 3126)
@@ -19,6 +19,8 @@
     ::1 -> 127.0.0.1 mapping.
   * any/cvs-isoc99_vscanf.diff: new patch from upstream to fix vscanf on
     non-GNU compilers.
+  * any/cvs-timer_delete.diff: new patch from upstream to fix a thread race
+    in glibc timer_delete.
 
   [ Samuel Thibault ]
   * patches/hurd-i386/cvs-lock-memory-clobber.diff: new patch from upstream

Added: glibc-package/trunk/debian/patches/any/cvs-timer_delete.diff
===================================================================
--- glibc-package/trunk/debian/patches/any/cvs-timer_delete.diff	                        (rev 0)
+++ glibc-package/trunk/debian/patches/any/cvs-timer_delete.diff	2008-09-09 14:12:12 UTC (rev 3126)
@@ -0,0 +1,146 @@
+2007-10-28  Ulrich Drepper  <drepper@redhat.com>
+
+	[BZ #5220]
+	* sysdeps/unix/sysv/linux/kernel-posix-timers.h: Declare
+	__active_timer_sigev_thread and __active_timer_sigev_thread_lock.
+	(struct timer): Add next element.
+	* sysdeps/unix/sysv/linux/timer_create.c: For SIGEV_THREAD timers,
+	enqueue timer structure into __active_timer_sigev_thread list.
+	* sysdeps/unix/sysv/linux/timer_delete.c: For SIGEV_THREAD timers,
+	remove timer struct from __active_timer_sigev_thread.
+	* sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread):
+	Before using timer structure make sure it is still on the
+	__active_timer_sigev_thread list.  Keep lock until done.
+	Define __active_timer_sigev_thread and
+	__active_timer_sigev_thread_lock.
+
+--- a/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h
++++ b/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h
+@@ -35,6 +35,11 @@ extern pthread_once_t __helper_once attribute_hidden;
+ /* TID of the helper thread.  */
+ extern pid_t __helper_tid attribute_hidden;
+ 
++/* List of active SIGEV_THREAD timers.  */
++extern struct timer *__active_timer_sigev_thread attribute_hidden;
++/* Lock for the __active_timer_sigev_thread.  */
++extern pthread_mutex_t __active_timer_sigev_thread_lock attribute_hidden;
++
+ 
+ /* Type of timers in the kernel.  */
+ typedef int kernel_timer_t;
+@@ -57,4 +62,7 @@ struct timer
+   void (*thrfunc) (sigval_t);
+   sigval_t sival;
+   pthread_attr_t attr;
++
++  /* Next element in list of active SIGEV_THREAD timers.  */
++  struct timer *next;
+ };
+--- a/nptl/sysdeps/unix/sysv/linux/timer_create.c
++++ b/nptl/sysdeps/unix/sysv/linux/timer_create.c
+@@ -206,6 +206,13 @@ timer_create (clock_id, evp, timerid)
+ 				      syscall_clockid, &sev, &newp->ktimerid);
+ 	      if (! INTERNAL_SYSCALL_ERROR_P (res, err))
+ 		{
++		  /* Add to the queue of active timers with thread
++		     delivery.  */
++		  pthread_mutex_lock (&__active_timer_sigev_thread_lock);
++		  newp->next = __active_timer_sigev_thread;
++		  __active_timer_sigev_thread = newp;
++		  pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
++
+ 		  *timerid = (timer_t) newp;
+ 		  return 0;
+ 		}
+--- a/nptl/sysdeps/unix/sysv/linux/timer_delete.c
++++ b/nptl/sysdeps/unix/sysv/linux/timer_delete.c
+@@ -54,6 +54,27 @@ timer_delete (timerid)
+ 
+       if (res == 0)
+ 	{
++	  if (kt->sigev_notify == SIGEV_THREAD)
++	    {
++	      /* Remove the timer from the list.  */
++	      pthread_mutex_lock (&__active_timer_sigev_thread_lock);
++	      if (__active_timer_sigev_thread == kt)
++		__active_timer_sigev_thread = kt->next;
++	      else
++		{
++		  struct timer *prevp = __active_timer_sigev_thread;
++		  while (prevp->next != NULL)
++		    if (prevp->next == kt)
++		      {
++			prevp->next = kt->next;
++			break;
++		      }
++		    else
++		      prevp = prevp->next;
++		}
++	      pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
++	    }
++
+ # ifndef __ASSUME_POSIX_TIMERS
+ 	  /* We know the syscall support is available.  */
+ 	  __no_posix_timers = 1;
+--- a/nptl/sysdeps/unix/sysv/linux/timer_routines.c
++++ b/nptl/sysdeps/unix/sysv/linux/timer_routines.c
+@@ -27,6 +27,12 @@
+ #include "kernel-posix-timers.h"
+ 
+ 
++/* List of active SIGEV_THREAD timers.  */
++struct timer *__active_timer_sigev_thread;
++/* Lock for the __active_timer_sigev_thread.  */
++pthread_mutex_t __active_timer_sigev_thread_lock = PTHREAD_MUTEX_INITIALIZER;
++
++
+ struct thread_start_data
+ {
+   void (*thrfunc) (sigval_t);
+@@ -95,19 +101,36 @@ timer_helper_thread (void *arg)
+ 	  if (si.si_code == SI_TIMER)
+ 	    {
+ 	      struct timer *tk = (struct timer *) si.si_ptr;
+-	      struct thread_start_data *td = malloc (sizeof (*td));
+ 
+-	      /* There is not much we can do if the allocation fails.  */
+-	      if (td != NULL)
+-		{
+-		  /* That is the signal we are waiting for.  */
+-		  td->thrfunc = tk->thrfunc;
+-		  td->sival = tk->sival;
++	      /* Check the timer is still used and will not go away
++		 while we are reading the values here.  */
++	      pthread_mutex_lock (&__active_timer_sigev_thread_lock);
+ 
+-		  pthread_t th;
+-		  (void) pthread_create (&th, &tk->attr, timer_sigev_thread,
+-					 td);
++	      struct timer *runp = __active_timer_sigev_thread;
++	      while (runp != NULL)
++		if (runp == tk)
++		  break;
++		else
++		  runp = runp->next;
++
++	      if (runp != NULL)
++		{
++		  struct thread_start_data *td = malloc (sizeof (*td));
++
++		  /* There is not much we can do if the allocation fails.  */
++		  if (td != NULL)
++		    {
++		      /* This is the signal we are waiting for.  */
++		      td->thrfunc = tk->thrfunc;
++		      td->sival = tk->sival;
++
++		      pthread_t th;
++		      (void) pthread_create (&th, &tk->attr,
++					     timer_sigev_thread, td);
++		    }
+ 		}
++
++	      pthread_mutex_unlock (&__active_timer_sigev_thread_lock);
+ 	    }
+ 	  else if (si.si_code == SI_TKILL)
+ 	    /* The thread is canceled.  */

Modified: glibc-package/trunk/debian/patches/series
===================================================================
--- glibc-package/trunk/debian/patches/series	2008-09-09 13:56:06 UTC (rev 3125)
+++ glibc-package/trunk/debian/patches/series	2008-09-09 14:12:12 UTC (rev 3126)
@@ -160,6 +160,7 @@
 any/cvs-rfc3484.diff -p1
 any/cvs-sched_h.diff -p0
 any/cvs-strtod.diff -p1
+any/cvs-timer_delete.diff
 any/cvs-tst-regex.diff -p1
 any/cvs-tzfile.diff -p1
 any/cvs-vfscanf.diff -p0


Reply to: