]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add another threads+signals test case along with the fix to make it work.
authorJulian Seward <jseward@acm.org>
Mon, 13 May 2002 00:38:52 +0000 (00:38 +0000)
committerJulian Seward <jseward@acm.org>
Mon, 13 May 2002 00:38:52 +0000 (00:38 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@267

coregrind/vg_signals.c
tests/pth_signal2.c [new file with mode: 0644]
vg_signals.c

index 3edff21b97e8ed07a47fda9041a8711f51e5aeba..20fad5880809e577981a70bd04a2a2cad23af423 100644 (file)
@@ -417,6 +417,7 @@ Bool VG_(deliver_signals) ( void )
         tst->m_edx = 0;
          tst->sh_edx = VGM_WORD_VALID;
          tst->status = VgTs_Runnable;
+         VG_(ksigemptyset)(&tst->sigs_waited_for);
          VG_(update_sigstate_following_WaitSIG_change)();
          vg_sigpending[sigNo] = VG_SP_SIGIDLE;
          continue; /* for (sigNo = 1; ...) loop */
diff --git a/tests/pth_signal2.c b/tests/pth_signal2.c
new file mode 100644 (file)
index 0000000..19976f7
--- /dev/null
@@ -0,0 +1,139 @@
+/********************************************************
+ * An example source module to accompany...
+ *
+ * "Using POSIX Threads: Programming with Pthreads"
+ *     by Brad nichols, Dick Buttlar, Jackie Farrell
+ *     O'Reilly & Associates, Inc.
+ *
+ ********************************************************
+ * stat_sigwait.c
+ *
+ * Simple example of pthreads and signals.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/types.h>
+
+#include <pthread.h>
+
+#define MAX_NUM_THREADS  10
+
+pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER;
+int mean, samples, total;
+
+void *report_stats(void *p)
+{
+  int caught;
+  sigset_t  sigs_to_catch;
+
+  /* Identify our thread */
+  printf("\nreport_stats() started.\n"); 
+
+  /*
+   * We inherited a thread sigmask with all the signals 
+   * blocked.  So, we can wait on whatever signals we're
+   * interested in and (as long as no other thread waits
+   * for them) we'll be sure return from sigwait() to
+   * handle it.
+   */ 
+
+  /* JRS 13 May 2002: this has a race condition, which is obvious if
+     you fire SIGUSR1s at it fast enough -- once sigwait returns,
+     there is no hander whilst it does the rest of the loop, so if a
+     signal arrives then, the program is killed, since that's the
+     default action for SIGUSR1. */
+
+  /* set this thread's signal mask to block out SIGUSR1 */
+  sigemptyset(&sigs_to_catch);
+  sigaddset(&sigs_to_catch, SIGUSR1);
+
+  for (;;) {
+     sigwait(&sigs_to_catch, &caught);
+
+     pthread_mutex_lock(&stats_lock);
+     mean = total/samples;
+     printf("\nreport_stats(): mean = %d, samples = %d\n", mean, samples);
+     pthread_mutex_unlock(&stats_lock);
+  }
+  return NULL;
+}
+/*
+ * worker_thread --
+ * 
+ * Don't read too much into what this thread does.  It's
+ * a very simpleminded example.  The only interesting thing
+ * it does is write to the global statistics data-- which
+ * means the thread processing the signal has to protect 
+ * against simultaneous access.
+ */
+void *worker_thread(void *p) 
+{
+  time_t now;
+  for (;;) {
+
+    sleep(1 + (*(int*)p) % 2 );
+  
+    now = time(NULL);
+    pthread_mutex_lock(&stats_lock);
+    total+=((int)now)%60; /* probably not the safest thing to do but
+                       it's just an example */
+    samples++;
+    pthread_mutex_unlock(&stats_lock);
+  }
+  /* Won't get here.  */
+  return NULL;
+}
+
+extern int
+main(void)
+{
+  int       i;
+  pthread_t threads[MAX_NUM_THREADS];
+  int       num_threads = 0;
+  sigset_t  sigs_to_block;
+
+
+  /* Identify our thread */
+  printf("main() (pid %d) running in thread 0x%x\n", 
+         getpid(), (int)pthread_self()); 
+
+  /* 
+   * Set this thread's signal mask to block SIGUSR1
+   * Other threads will inherit the mask
+   */
+  sigemptyset(&sigs_to_block);
+  sigaddset(&sigs_to_block, SIGUSR1);
+  pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL);
+
+  /* spawn statistics reporting thread */
+  pthread_create(&threads[num_threads++],
+                NULL,
+                report_stats,
+                NULL);
+
+  /* spawn the threads */
+  for (i=num_threads; i<MAX_NUM_THREADS; i++) {
+    pthread_create(&threads[num_threads++],
+                  NULL,
+                   worker_thread,
+                  &i);
+  }
+  printf("main()\t\t\t\t%d threads created\n",num_threads);
+  
+  /* wait until all threads have finished */
+  for (i = 0; i < num_threads; i++) {
+    pthread_join(threads[i], NULL);
+    printf("main()\t\tjoined to thread %d \n", i);
+  }
+  
+  printf("main()\t\tall %d threads have finished. \n", num_threads);
+
+  return 0;
+}
+
index 3edff21b97e8ed07a47fda9041a8711f51e5aeba..20fad5880809e577981a70bd04a2a2cad23af423 100644 (file)
@@ -417,6 +417,7 @@ Bool VG_(deliver_signals) ( void )
         tst->m_edx = 0;
          tst->sh_edx = VGM_WORD_VALID;
          tst->status = VgTs_Runnable;
+         VG_(ksigemptyset)(&tst->sigs_waited_for);
          VG_(update_sigstate_following_WaitSIG_change)();
          vg_sigpending[sigNo] = VG_SP_SIGIDLE;
          continue; /* for (sigNo = 1; ...) loop */