Kannel: Open Source WAP and SMS gateway  svn-r5335
gwthread-pthread.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * gwthread-pthread.c - implementation of gwthread.h using POSIX threads.
59  *
60  * Richard Braakman
61  */
62 
63 #include <unistd.h>
64 #include <errno.h>
65 #include <pthread.h>
66 #include <signal.h>
67 #include <string.h>
68 
69 #include "gwlib/gwlib.h"
70 
71 #ifdef HAVE_LIBSSL
72 #include <openssl/err.h>
73 #endif /* HAVE_LIBSSL */
74 
75 /* Maximum number of live threads we can support at once. Increasing
76  * this will increase the size of the threadtable. Use powers of two
77  * for efficiency. */
78 #define THREADTABLE_SIZE 4096
79 
80 struct threadinfo
81 {
82  pthread_t self;
83  const char *name;
85  long number;
88  /* joiners may be NULL. It is not allocated until a thread wants
89  * to register. This is safe because the thread table is always
90  * locked when a thread accesses this field. */
92  pid_t pid;
93 };
94 
96 {
98  void *arg;
99  struct threadinfo *ti;
100  /* signals already started thread to die */
101  int failed;
102 };
103 
104 /* The index is the external thread number modulo the table size; the
105  * thread number allocation code makes sure that there are no collisions. */
107 #define THREAD(t) (threadtable[(t) % THREADTABLE_SIZE])
108 
109 /* Number of threads currently in the thread table. */
110 static long active_threads = 0;
111 
112 /* Number to use for the next thread created. The actual number used
113  * may be higher than this, in order to avoid collisions in the threadtable.
114  * Specifically, (threadnumber % THREADTABLE_SIZE) must be unique for all
115  * live threads. */
116 static long next_threadnumber;
117 
118 /* Info for the main thread is kept statically, because it should not
119  * be deallocated even after the thread module shuts down -- after all,
120  * the main thread is still running, and in practice, it can still
121  * output debug messages which will require the thread number. */
122 static struct threadinfo mainthread;
123 
124 /* Our key for accessing the (struct gwthread *) we stash in the
125  * thread-specific-data area. This is much more efficient than
126  * accessing a global table, which we would have to lock. */
127 static pthread_key_t tsd_key;
128 
129 static pthread_mutex_t threadtable_lock;
130 
131 static void inline lock(void)
132 {
133  int ret;
134 
135  ret = pthread_mutex_lock(&threadtable_lock);
136  if (ret != 0) {
137  panic(ret, "gwthread-pthread: could not lock thread table");
138  }
139 }
140 
141 static void inline unlock(void)
142 {
143  int ret;
144 
145  ret = pthread_mutex_unlock(&threadtable_lock);
146  if (ret != 0) {
147  panic(ret, "gwthread-pthread: could not unlock thread table");
148  }
149 }
150 
151 /* Empty the wakeup pipe, in case we got several wakeup signals before
152  * noticing. We want to wake up only once. */
153 static void flushpipe(int fd)
154 {
155  unsigned char buf[128];
156  ssize_t bytes;
157 
158  do {
159  bytes = read(fd, buf, sizeof(buf));
160  } while (bytes > 0);
161 }
162 
163 /* Allocate and fill a threadinfo structure for a new thread, and store
164  * it in a free slot in the thread table. The thread table must already
165  * be locked by the caller. Return the thread number chosen for this
166  * thread. The caller must make sure that there is room in the table. */
167 static long fill_threadinfo(pthread_t id, const char *name,
169  struct threadinfo *ti)
170 {
171  int pipefds[2];
172  long first_try;
173 
175 
176  /* initialize to default values */
177  ti->self = id;
178  ti->name = name;
179  ti->func = func;
180  ti->pid = -1;
181  ti->wakefd_recv = -1;
182  ti->wakefd_send = -1;
183  ti->joiners = NULL;
184  ti->number = -1;
185 
186  if (pipe(pipefds) < 0) {
187  error(errno, "cannot allocate wakeup pipe for new thread");
188  return -1;
189  }
190  ti->wakefd_recv = pipefds[0];
191  ti->wakefd_send = pipefds[1];
194 
195  /* Find a free table entry and claim it. */
196  first_try = next_threadnumber;
197  do {
198  ti->number = next_threadnumber++;
199  /* Check if we looped all the way around the thread table. */
200  if (ti->number == first_try + THREADTABLE_SIZE) {
201  error(0, "Cannot have more than %d active threads", THREADTABLE_SIZE);
202  ti->number = -1;
203  close(ti->wakefd_recv);
204  ti->wakefd_recv = -1;
205  close(ti->wakefd_send);
206  ti->wakefd_send = -1;
207  return -1;
208  }
209  } while (THREAD(ti->number) != NULL);
210  THREAD(ti->number) = ti;
211 
212  active_threads++;
213 
214  return ti->number;
215 }
216 
217 /* Look up the threadinfo pointer for the current thread */
218 static struct threadinfo *getthreadinfo(void)
219 {
220  struct threadinfo *threadinfo;
221 
222  threadinfo = pthread_getspecific(tsd_key);
223  if (threadinfo == NULL) {
224  panic(0, "gwthread-pthread: pthread_getspecific failed");
225  } else {
226  gw_assert(pthread_equal(threadinfo->self, pthread_self()));
227  }
228  return threadinfo;
229 }
230 
231 /*
232  * Go through the list of threads waiting for us to exit, and tell
233  * them that we're exiting. The joiner_cond entries are registered
234  * by those threads, and will be cleaned up by them.
235  */
236 static void alert_joiners(void)
237 {
238  struct threadinfo *threadinfo;
239  pthread_cond_t *joiner_cond;
240 
242  if (!threadinfo->joiners)
243  return;
244  while ((joiner_cond = gwlist_extract_first(threadinfo->joiners))) {
245  pthread_cond_broadcast(joiner_cond);
246  }
247 }
248 
249 static void delete_threadinfo(void)
250 {
251  struct threadinfo *threadinfo;
252 
255  if (threadinfo->wakefd_recv != -1)
256  close(threadinfo->wakefd_recv);
257  if (threadinfo->wakefd_send != -1)
258  close(threadinfo->wakefd_send);
259  if (threadinfo->number != -1) {
260  THREAD(threadinfo->number) = NULL;
261  active_threads--;
262  }
264  gw_free(threadinfo);
265 }
266 
267 void gwthread_init(void)
268 {
269  int ret;
270  int i;
271 
272  pthread_mutex_init(&threadtable_lock, NULL);
273 
274  ret = pthread_key_create(&tsd_key, NULL);
275  if (ret != 0) {
276  panic(ret, "gwthread-pthread: pthread_key_create failed");
277  }
278 
279  for (i = 0; i < THREADTABLE_SIZE; i++) {
280  threadtable[i] = NULL;
281  }
282  active_threads = 0;
283 
284  /* create main thread info */
285  if (fill_threadinfo(pthread_self(), "main", NULL, &mainthread) == -1)
286  panic(0, "gwthread-pthread: unable to fill main threadinfo.");
287 
288  ret = pthread_setspecific(tsd_key, &mainthread);
289  if (ret != 0)
290  panic(ret, "gwthread-pthread: pthread_setspecific failed");
291 }
292 
293 /* Note that the gwthread library can't shut down completely, because
294  * the main thread will still be running, and it may make calls to
295  * gwthread_self(). */
297 {
298  int ret;
299  int running;
300  int i;
301 
302  /* Main thread must not have disappeared */
303  gw_assert(threadtable[0] != NULL);
304  lock();
305 
306  running = 0;
307  /* Start i at 1 to skip the main thread, which is supposed to be
308  * still running. */
309  for (i = 1; i < THREADTABLE_SIZE; i++) {
310  if (threadtable[i] != NULL) {
311  debug("gwlib", 0, "Thread %ld (%s) still running",
312  threadtable[i]->number,
313  threadtable[i]->name);
314  running++;
315  }
316  }
317  unlock();
318 
319  /* We can't do a full cleanup this way */
320  if (running)
321  return;
322 
323  ret = pthread_mutex_destroy(&threadtable_lock);
324  if (ret != 0) {
325  warning(ret, "cannot destroy threadtable lock");
326  }
327 
328  /* We can't delete the tsd_key here, because gwthread_self()
329  * still needs it to access the main thread's info. */
330 }
331 
332 static void new_thread_cleanup(void *arg)
333 {
334  struct new_thread_args *p = arg;
335 
336  lock();
337  debug("gwlib.gwthread", 0, "Thread %ld (%s) terminates.",
338  p->ti->number, p->ti->name);
339  alert_joiners();
340 #ifdef HAVE_LIBSSL
341 #if OPENSSL_VERSION_NUMBER < 0x10100000L
342  /* Clear the OpenSSL thread-specific error queue to avoid
343  * memory leaks. */
344  ERR_remove_state(gwthread_self());
345 #endif
346 #endif /* HAVE_LIBSSL */
347  /* Must free p before signaling our exit, otherwise there is
348  * a race with gw_check_leaks at shutdown. */
349  gw_free(p);
351  unlock();
352 }
353 
354 static void *new_thread(void *arg)
355 {
356  int ret;
357  struct new_thread_args *p = arg;
358 
359  /* Make sure we don't start until our parent has entered
360  * our thread info in the thread table. */
361  lock();
362  /* check for initialization errors */
363  if (p->failed) {
364  /* Must free p before signaling our exit, otherwise there is
365  * a race with gw_check_leaks at shutdown. */
366  gw_free(p->ti);
367  gw_free(p);
368  unlock();
369  return NULL;
370  }
371  unlock();
372 
373  /* This has to be done here, because pthread_setspecific cannot
374  * be called by our parent on our behalf. That's why the ti
375  * pointer is passed in the new_thread_args structure. */
376  /* Synchronization is not a problem, because the only thread
377  * that relies on this call having been made is this one --
378  * no other thread can access our TSD anyway. */
379  ret = pthread_setspecific(tsd_key, p->ti);
380  if (ret != 0) {
381  panic(ret, "gwthread-pthread: pthread_setspecific failed");
382  }
383 
384  p->ti->pid = getpid();
385  debug("gwlib.gwthread", 0, "Thread %ld (%s) maps to pid %ld.",
386  p->ti->number, p->ti->name, (long) p->ti->pid);
387 
388  /* set cancel cleanup function */
389  pthread_cleanup_push(new_thread_cleanup, p);
390 
391  (p->func)(p->arg);
392 
393  pthread_cleanup_pop(0);
394 
396 
397  return NULL;
398 }
399 
400 /*
401  * Change this thread's signal mask to block user-visible signals
402  * (HUP, TERM, QUIT, INT), and store the old signal mask in
403  * *old_set_storage.
404  * Return 0 for success, or -1 if an error occurred.
405  */
406 
407  /*
408  * This does not work in Darwin alias MacOS X alias Mach kernel,
409  * however. So we define a dummy function doing nothing.
410  */
411 #if defined(DARWIN_OLD)
412  static int pthread_sigmask();
413 #endif
414 
415 static int block_user_signals(sigset_t *old_set_storage)
416 {
417  int ret;
418  sigset_t block_signals;
419 
420  ret = sigemptyset(&block_signals);
421  if (ret != 0) {
422  error(errno, "gwthread-pthread: Couldn't initialize signal set");
423  return -1;
424  }
425  ret = sigaddset(&block_signals, SIGHUP);
426  ret |= sigaddset(&block_signals, SIGTERM);
427  ret |= sigaddset(&block_signals, SIGQUIT);
428  ret |= sigaddset(&block_signals, SIGINT);
429  if (ret != 0) {
430  error(0, "gwthread-pthread: Couldn't add signal to signal set");
431  return -1;
432  }
433  ret = pthread_sigmask(SIG_BLOCK, &block_signals, old_set_storage);
434  if (ret != 0) {
435  error(ret,
436  "gwthread-pthread: Couldn't disable signals for thread creation");
437  return -1;
438  }
439  return 0;
440 }
441 
442 static void restore_user_signals(sigset_t *old_set)
443 {
444  int ret;
445 
446  ret = pthread_sigmask(SIG_SETMASK, old_set, NULL);
447  if (ret != 0) {
448  panic(ret, "gwthread-pthread: Couldn't restore signal set.");
449  }
450 }
451 
452 
453 static long spawn_thread(gwthread_func_t *func, const char *name, void *arg)
454 {
455  int ret;
456  pthread_t id;
457  struct new_thread_args *p = NULL;
458  long new_thread_id;
459 
460  /* We want to pass both these arguments to our wrapper function
461  * new_thread, but the pthread_create interface will only let
462  * us pass one pointer. So we wrap them in a little struct. */
463  p = gw_malloc(sizeof(*p));
464  p->func = func;
465  p->arg = arg;
466  p->ti = gw_malloc(sizeof(*(p->ti)));
467  p->failed = 0;
468 
469  /* Lock the thread table here, so that new_thread can block
470  * on that lock. That way, the new thread won't start until
471  * we have entered it in the thread table. */
472  lock();
473 
475  unlock();
476  error(0, "Too many threads, could not create new thread.");
477  gw_free(p->ti);
478  gw_free(p);
479  return -1;
480  }
481 
482  ret = pthread_create(&id, NULL, &new_thread, p);
483  if (ret != 0) {
484  unlock();
485  error(ret, "Could not create new thread.");
486  gw_free(p->ti);
487  gw_free(p);
488  return -1;
489  }
490  ret = pthread_detach(id);
491  if (ret != 0) {
492  error(ret, "Could not detach new thread.");
493  }
494 
495  new_thread_id = fill_threadinfo(id, name, func, p->ti);
496  if (new_thread_id == -1)
497  p->failed = 1;
498  unlock();
499 
500  if (new_thread_id != -1)
501  debug("gwlib.gwthread", 0, "Started thread %ld (%s)", new_thread_id, name);
502  else
503  debug("gwlib.gwthread", 0, "Failed to start thread (%s)", name);
504 
505  return new_thread_id;
506 }
507 
509 {
510  int sigtrick = 0;
511  sigset_t old_signal_set;
512  long thread_id;
513 
514  /*
515  * We want to make sure that only the main thread handles signals,
516  * so that each signal is handled exactly once. To do this, we
517  * make sure that each new thread has all the signals that we
518  * handle blocked. To avoid race conditions, we block them in
519  * the spawning thread first, then create the new thread (which
520  * inherits the settings), and then restore the old settings in
521  * the spawning thread. This means that there is a brief period
522  * when no signals will be processed, but during that time they
523  * should be queued by the operating system.
524  */
525  if (gwthread_self() == MAIN_THREAD_ID)
526  sigtrick = block_user_signals(&old_signal_set) == 0;
527 
528  thread_id = spawn_thread(func, name, arg);
529 
530  /*
531  * Restore the old signal mask. The new thread will have
532  * inherited the resticted one, but the main thread needs
533  * the old one back.
534  */
535  if (sigtrick)
536  restore_user_signals(&old_signal_set);
537 
538  return thread_id;
539 }
540 
541 void gwthread_join(long thread)
542 {
543  struct threadinfo *threadinfo;
544  pthread_cond_t exit_cond;
545  int ret;
546 
547  gw_assert(thread >= 0);
548 
549  lock();
550  threadinfo = THREAD(thread);
551  if (threadinfo == NULL || threadinfo->number != thread) {
552  /* The other thread has already exited */
553  unlock();
554  return;
555  }
556 
557  /* Register our desire to be alerted when that thread exits,
558  * and wait for it. */
559 
560  ret = pthread_cond_init(&exit_cond, NULL);
561  if (ret != 0) {
562  warning(ret, "gwthread_join: cannot create condition variable.");
563  unlock();
564  return;
565  }
566 
567  if (!threadinfo->joiners)
569  gwlist_append(threadinfo->joiners, &exit_cond);
570 
571  /* The wait immediately releases the lock, and reacquires it
572  * when the condition is satisfied. So don't worry, we're not
573  * blocking while keeping the table locked. */
574  pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, &threadtable_lock);
575  ret = pthread_cond_wait(&exit_cond, &threadtable_lock);
576  pthread_cleanup_pop(0);
577  unlock();
578 
579  if (ret != 0)
580  warning(ret, "gwthread_join: error in pthread_cond_wait");
581 
582  pthread_cond_destroy(&exit_cond);
583 }
584 
586 {
587  long i;
588  long our_thread = gwthread_self();
589 
590  for (i = 0; i < THREADTABLE_SIZE; ++i) {
591  if (THREAD(our_thread) != THREAD(i))
592  gwthread_join(i);
593  }
594 }
595 
597 {
598  long i;
599  long our_thread = gwthread_self();
600 
601  for (i = 0; i < THREADTABLE_SIZE; ++i) {
602  if (THREAD(our_thread) != THREAD(i))
603  gwthread_wakeup(i);
604  }
605 }
606 
608 {
609  struct threadinfo *ti;
610  pthread_cond_t exit_cond;
611  int ret;
612  long i;
613 
614  ret = pthread_cond_init(&exit_cond, NULL);
615  if (ret != 0) {
616  warning(ret, "gwthread_join_every: cannot create condition variable.");
617  unlock();
618  return;
619  }
620 
621  /*
622  * FIXME: To be really safe, this function should keep looping
623  * over the table until it does a complete run without having
624  * to call pthread_cond_wait. Otherwise, new threads could
625  * start while we wait, and we'll miss them.
626  */
627  lock();
628  for (i = 0; i < THREADTABLE_SIZE; ++i) {
629  ti = THREAD(i);
630  if (ti == NULL || ti->func != func)
631  continue;
632  debug("gwlib.gwthread", 0,
633  "Waiting for %ld (%s) to terminate",
634  ti->number, ti->name);
635  if (!ti->joiners)
636  ti->joiners = gwlist_create();
637  gwlist_append(ti->joiners, &exit_cond);
638  pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, &threadtable_lock);
639  ret = pthread_cond_wait(&exit_cond, &threadtable_lock);
640  pthread_cleanup_pop(0);
641  if (ret != 0)
642  warning(ret, "gwthread_join_all: error in pthread_cond_wait");
643  }
644  unlock();
645 
646  pthread_cond_destroy(&exit_cond);
647 }
648 
649 /* Return the thread id of this thread. */
650 long gwthread_self(void)
651 {
652  struct threadinfo *threadinfo;
653  threadinfo = pthread_getspecific(tsd_key);
654  if (threadinfo)
655  return threadinfo->number;
656  else
657  return -1;
658 }
659 
660 /* Return the thread pid of this thread. */
662 {
663  struct threadinfo *threadinfo;
664  threadinfo = pthread_getspecific(tsd_key);
665  if (threadinfo && threadinfo->pid != -1)
666  return (long) threadinfo->pid;
667  else
668  return (long) getpid();
669 }
670 
671 void gwthread_self_ids(long *tid, long *pid)
672 {
673  struct threadinfo *threadinfo;
674  threadinfo = pthread_getspecific(tsd_key);
675  if (threadinfo) {
676  *tid = threadinfo->number;
677  *pid = (threadinfo->pid != -1) ? threadinfo->pid : getpid();
678  } else {
679  *tid = -1;
680  *pid = getpid();
681  }
682 }
683 
684 void gwthread_wakeup(long thread)
685 {
686  unsigned char c = 0;
687  struct threadinfo *threadinfo;
688  int fd;
689 
690  gw_assert(thread >= 0);
691 
692  lock();
693 
694  threadinfo = THREAD(thread);
695  if (threadinfo == NULL || threadinfo->number != thread) {
696  unlock();
697  return;
698  }
699 
700  fd = threadinfo->wakefd_send;
701  unlock();
702 
703  write(fd, &c, 1);
704 }
705 
706 int gwthread_pollfd(int fd, int events, double timeout)
707 {
708  struct pollfd pollfd[2];
709  struct threadinfo *threadinfo;
710  int milliseconds;
711  int ret;
712 
714 
716  pollfd[0].events = POLLIN;
717  pollfd[0].revents = 0;
718 
719  pollfd[1].fd = fd;
720  pollfd[1].events = events;
721  pollfd[1].revents = 0;
722 
723  milliseconds = timeout * 1000;
724  if (milliseconds < 0)
725  milliseconds = POLL_NOTIMEOUT;
726 
727  ret = poll(pollfd, 2, milliseconds);
728  if (ret < 0) {
729  if (errno != EINTR)
730  error(errno, "gwthread_pollfd: error in poll");
731  return -1;
732  }
733 
734  if (pollfd[0].revents)
735  flushpipe(pollfd[0].fd);
736 
737  return pollfd[1].revents;
738 }
739 
740 int gwthread_poll(struct pollfd *fds, long numfds, double timeout)
741 {
742  struct pollfd *pollfds;
743  struct threadinfo *threadinfo;
744  int milliseconds;
745  int ret;
746 
748 
749  /* Create a new pollfd array with an extra element for the
750  * thread wakeup fd. */
751 
752  pollfds = gw_malloc((numfds + 1) * sizeof(*pollfds));
753  pollfds[0].fd = threadinfo->wakefd_recv;
754  pollfds[0].events = POLLIN;
755  pollfds[0].revents = 0;
756  memcpy(pollfds + 1, fds, numfds * sizeof(*pollfds));
757 
758  milliseconds = timeout * 1000;
759  if (milliseconds < 0)
760  milliseconds = POLL_NOTIMEOUT;
761 
762  ret = poll(pollfds, numfds + 1, milliseconds);
763  if (ret < 0) {
764  if (errno != EINTR)
765  error(errno, "gwthread_poll: error in poll");
766  gw_free(pollfds);
767  return -1;
768  }
769  if (pollfds[0].revents)
770  flushpipe(pollfds[0].fd);
771 
772  /* Copy the results back to the caller */
773  memcpy(fds, pollfds + 1, numfds * sizeof(*pollfds));
774  gw_free(pollfds);
775 
776  return ret;
777 }
778 
779 
780 void gwthread_sleep(double seconds)
781 {
782  struct pollfd pollfd;
783  struct threadinfo *threadinfo;
784  int milliseconds;
785  int ret;
786 
788 
790  pollfd.events = POLLIN;
791 
792  milliseconds = seconds * 1000;
793  if (milliseconds < 0)
794  milliseconds = POLL_NOTIMEOUT;
795 
796  ret = poll(&pollfd, 1, milliseconds);
797  if (ret < 0) {
798  if (errno != EINTR && errno != EAGAIN) {
799  warning(errno, "gwthread_sleep: error in poll");
800  }
801  }
802  if (ret == 1) {
804  }
805 }
806 
807 
808 void gwthread_sleep_micro(double dseconds)
809 {
810  fd_set fd_set_recv;
811  struct threadinfo *threadinfo;
812  int fd;
813  int ret;
814 
816  fd = threadinfo->wakefd_recv;
817 
818  FD_ZERO(&fd_set_recv);
819  FD_SET(fd, &fd_set_recv);
820 
821  if (dseconds < 0) {
822  ret = select(fd + 1, &fd_set_recv, NULL, NULL, NULL);
823  } else {
824  struct timeval timeout;
825  timeout.tv_sec = dseconds;
826  timeout.tv_usec = (dseconds - timeout.tv_sec) * 1000000;
827 
828  ret = select(fd + 1, &fd_set_recv, NULL, NULL, &timeout);
829  }
830 
831  if (ret < 0) {
832  if (errno != EINTR && errno != EAGAIN) {
833  warning(errno, "gwthread_sleep_micro: error in select()");
834  }
835  }
836 
837  if (FD_ISSET(fd, &fd_set_recv)) {
838  flushpipe(fd);
839  }
840 }
841 
842 
843 int gwthread_cancel(long thread)
844 {
845  struct threadinfo *threadinfo;
846  int ret;
847 
848  gw_assert(thread >= 0);
849 
850  lock();
851  threadinfo = THREAD(thread);
852  if (threadinfo == NULL || threadinfo->number != thread) {
853  ret = -1;
854  } else {
855  ret = pthread_cancel(threadinfo->self);
856  debug("gwlib.gwthread", 0, "Thread %ld (%s) canceled.",
858  }
859  unlock();
860  return ret;
861 }
862 
863 
864 #ifndef BROKEN_PTHREADS
865 
866 /* Working pthreads */
868  return 1;
869 }
870 #else
871 
872 /* Somewhat broken pthreads */
873 int gwthread_shouldhandlesignal(int signal){
874  return (gwthread_self() == MAIN_THREAD_ID);
875 }
876 #endif
877 
879  sigset_t signal_set;
880  int signum;
881 
882  /* Grab the signal set data from our thread */
883  if (pthread_sigmask(SIG_BLOCK, NULL, &signal_set) != 0) {
884  warning(0, "gwthread_dumpsigmask: Couldn't get signal mask.");
885  return -1;
886  }
887 
888  /* For each signal normally defined (there are usually only 32),
889  * print a message if we don't block it. */
890  for (signum = 1; signum <= 32; signum++) {
891  if (!sigismember(&signal_set, signum)) {
892  debug("gwlib", 0,
893  "gwthread_dumpsigmask: Signal Number %d will be caught.",
894  signum);
895  }
896  }
897  return 0;
898 }
899 
900 /* DARWIN alias MacOS X doesnt have pthread_sigmask in its pthreads implementation */
901 
902 #if defined(DARWIN_OLD)
903 static int pthread_sigmask()
904 {
905  return 0;
906 }
907 #endif
#define THREADTABLE_SIZE
void error(int err, const char *fmt,...)
Definition: log.c:648
int number
Definition: smsc_cimd2.c:213
void gwthread_join_all(void)
int socket_set_blocking(int fd, int blocking)
Definition: socket.c:368
static struct threadinfo * threadtable[THREADTABLE_SIZE]
gwthread_func_t * func
long gwthread_self(void)
struct threadinfo * ti
static void new_thread_cleanup(void *arg)
gw_assert(wtls_machine->packet_to_send !=NULL)
void gwlist_append(List *list, void *item)
Definition: list.c:179
Definition: shared.h:81
void gwthread_join(long thread)
#define poll(fdarray, numfds, timeout)
Definition: gwpoll.h:104
void gwthread_sleep_micro(double dseconds)
#define POLL_NOTIMEOUT
Definition: gwpoll.h:100
const char * name
int gwthread_shouldhandlesignal(int signal)
void gwthread_self_ids(long *tid, long *pid)
int gwthread_poll(struct pollfd *fds, long numfds, double timeout)
void gwthread_join_every(gwthread_func_t *func)
short events
Definition: gwpoll.h:86
static long next_threadnumber
gwthread_func_t * func
void gwthread_func_t(void *arg)
Definition: gwthread.h:79
static long active_threads
#define POLLIN
Definition: gwpoll.h:91
long gwthread_self_pid(void)
void * gwlist_extract_first(List *list)
Definition: list.c:305
static struct threadinfo * getthreadinfo(void)
static void delete_threadinfo(void)
void gwthread_shutdown(void)
char * name
Definition: smsc_cimd2.c:212
void warning(int err, const char *fmt,...)
Definition: log.c:660
Definition: gwpoll.h:84
static void alert_joiners(void)
void gwthread_sleep(double seconds)
static long fill_threadinfo(pthread_t id, const char *name, gwthread_func_t *func, struct threadinfo *ti)
static struct threadinfo mainthread
int gwthread_pollfd(int fd, int events, double timeout)
static void unlock(void)
int fd
Definition: gwpoll.h:85
static pthread_mutex_t threadtable_lock
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
#define THREAD(t)
#define panic
Definition: log.h:87
void gwthread_wakeup(long thread)
static pthread_key_t tsd_key
short revents
Definition: gwpoll.h:87
#define gwlist_create()
Definition: list.h:136
static void lock(void)
pthread_t self
long gwthread_create_real(gwthread_func_t *func, const char *name, void *arg)
int gwthread_cancel(long thread)
#define MAIN_THREAD_ID
Definition: gwthread.h:77
static long spawn_thread(gwthread_func_t *func, const char *name, void *arg)
static void restore_user_signals(sigset_t *old_set)
void gwthread_wakeup_all(void)
void gwthread_init(void)
static void flushpipe(int fd)
Definition: list.c:102
static int block_user_signals(sigset_t *old_set_storage)
static void * new_thread(void *arg)
int gwthread_dumpsigmask(void)
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)
Definition: list.c:145
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.