1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2014 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 1024
79 
80 struct threadinfo
81 {
82     pthread_t self;
83     const char *name;
84     gwthread_func_t *func;
85     long number;
86     int wakefd_recv;
87     int wakefd_send;
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. */
91     List *joiners;
92     pid_t pid;
93 };
94 
95 struct new_thread_args
96 {
97     gwthread_func_t *func;
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. */
106 static struct threadinfo *threadtable[THREADTABLE_SIZE];
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 
lock(void)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 
unlock(void)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. */
flushpipe(int fd)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. */
fill_threadinfo(pthread_t id,const char * name,gwthread_func_t * func,struct threadinfo * ti)167 static long fill_threadinfo(pthread_t id, const char *name,
168                             gwthread_func_t *func,
169                             struct threadinfo *ti)
170 {
171     int pipefds[2];
172     long first_try;
173 
174     gw_assert(active_threads < THREADTABLE_SIZE);
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];
192     socket_set_blocking(ti->wakefd_recv, 0);
193     socket_set_blocking(ti->wakefd_send, 0);
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             return -1;
204         }
205     } while (THREAD(ti->number) != NULL);
206     THREAD(ti->number) = ti;
207 
208     active_threads++;
209 
210     return ti->number;
211 }
212 
213 /* Look up the threadinfo pointer for the current thread */
getthreadinfo(void)214 static struct threadinfo *getthreadinfo(void)
215 {
216     struct threadinfo *threadinfo;
217 
218     threadinfo = pthread_getspecific(tsd_key);
219     if (threadinfo == NULL) {
220         panic(0, "gwthread-pthread: pthread_getspecific failed");
221     } else {
222         gw_assert(pthread_equal(threadinfo->self, pthread_self()));
223     }
224     return threadinfo;
225 }
226 
227 /*
228  * Go through the list of threads waiting for us to exit, and tell
229  * them that we're exiting.  The joiner_cond entries are registered
230  * by those threads, and will be cleaned up by them.
231  */
alert_joiners(void)232 static void alert_joiners(void)
233 {
234     struct threadinfo *threadinfo;
235     pthread_cond_t *joiner_cond;
236 
237     threadinfo = getthreadinfo();
238     if (!threadinfo->joiners)
239         return;
240     while ((joiner_cond = gwlist_extract_first(threadinfo->joiners))) {
241         pthread_cond_broadcast(joiner_cond);
242     }
243 }
244 
delete_threadinfo(void)245 static void delete_threadinfo(void)
246 {
247     struct threadinfo *threadinfo;
248 
249     threadinfo = getthreadinfo();
250     gwlist_destroy(threadinfo->joiners, NULL);
251     if (threadinfo->wakefd_recv != -1)
252         close(threadinfo->wakefd_recv);
253     if (threadinfo->wakefd_send != -1)
254         close(threadinfo->wakefd_send);
255     if (threadinfo->number != -1) {
256         THREAD(threadinfo->number) = NULL;
257         active_threads--;
258     }
259     gw_assert(threadinfo != &mainthread);
260     gw_free(threadinfo);
261 }
262 
gwthread_init(void)263 void gwthread_init(void)
264 {
265     int ret;
266     int i;
267 
268     pthread_mutex_init(&threadtable_lock, NULL);
269 
270     ret = pthread_key_create(&tsd_key, NULL);
271     if (ret != 0) {
272         panic(ret, "gwthread-pthread: pthread_key_create failed");
273     }
274 
275     for (i = 0; i < THREADTABLE_SIZE; i++) {
276         threadtable[i] = NULL;
277     }
278     active_threads = 0;
279 
280     /* create main thread info */
281     if (fill_threadinfo(pthread_self(), "main", NULL, &mainthread) == -1)
282         panic(0, "gwthread-pthread: unable to fill main threadinfo.");
283 
284     ret = pthread_setspecific(tsd_key, &mainthread);
285     if (ret != 0)
286         panic(ret, "gwthread-pthread: pthread_setspecific failed");
287 }
288 
289 /* Note that the gwthread library can't shut down completely, because
290  * the main thread will still be running, and it may make calls to
291  * gwthread_self(). */
gwthread_shutdown(void)292 void gwthread_shutdown(void)
293 {
294     int ret;
295     int running;
296     int i;
297 
298     /* Main thread must not have disappeared */
299     gw_assert(threadtable[0] != NULL);
300     lock();
301 
302     running = 0;
303     /* Start i at 1 to skip the main thread, which is supposed to be
304      * still running. */
305     for (i = 1; i < THREADTABLE_SIZE; i++) {
306         if (threadtable[i] != NULL) {
307             debug("gwlib", 0, "Thread %ld (%s) still running",
308                   threadtable[i]->number,
309                   threadtable[i]->name);
310             running++;
311         }
312     }
313     unlock();
314 
315     /* We can't do a full cleanup this way */
316     if (running)
317         return;
318 
319     ret = pthread_mutex_destroy(&threadtable_lock);
320     if (ret != 0) {
321         warning(ret, "cannot destroy threadtable lock");
322     }
323 
324     /* We can't delete the tsd_key here, because gwthread_self()
325      * still needs it to access the main thread's info. */
326 }
327 
new_thread_cleanup(void * arg)328 static void new_thread_cleanup(void *arg)
329 {
330     struct new_thread_args *p = arg;
331 
332     lock();
333     debug("gwlib.gwthread", 0, "Thread %ld (%s) terminates.",
334           p->ti->number, p->ti->name);
335     alert_joiners();
336 #ifdef HAVE_LIBSSL
337     /* Clear the OpenSSL thread-specific error queue to avoid
338      * memory leaks. */
339     ERR_remove_state(gwthread_self());
340 #endif /* HAVE_LIBSSL */
341     /* Must free p before signaling our exit, otherwise there is
342      * a race with gw_check_leaks at shutdown. */
343     gw_free(p);
344     delete_threadinfo();
345     unlock();
346 }
347 
new_thread(void * arg)348 static void *new_thread(void *arg)
349 {
350     int ret;
351     struct new_thread_args *p = arg;
352 
353     /* Make sure we don't start until our parent has entered
354      * our thread info in the thread table. */
355     lock();
356     /* check for initialization errors */
357     if (p->failed) {
358         /* Must free p before signaling our exit, otherwise there is
359         * a race with gw_check_leaks at shutdown. */
360         gw_free(p);
361         delete_threadinfo();
362         unlock();
363         return NULL;
364     }
365     unlock();
366 
367     /* This has to be done here, because pthread_setspecific cannot
368      * be called by our parent on our behalf.  That's why the ti
369      * pointer is passed in the new_thread_args structure. */
370     /* Synchronization is not a problem, because the only thread
371      * that relies on this call having been made is this one --
372      * no other thread can access our TSD anyway. */
373     ret = pthread_setspecific(tsd_key, p->ti);
374     if (ret != 0) {
375         panic(ret, "gwthread-pthread: pthread_setspecific failed");
376     }
377 
378     p->ti->pid = getpid();
379     debug("gwlib.gwthread", 0, "Thread %ld (%s) maps to pid %ld.",
380           p->ti->number, p->ti->name, (long) p->ti->pid);
381 
382     /* set cancel cleanup function */
383     pthread_cleanup_push(new_thread_cleanup, p);
384 
385     (p->func)(p->arg);
386 
387     pthread_cleanup_pop(0);
388 
389     new_thread_cleanup(p);
390 
391     return NULL;
392 }
393 
394 /*
395  * Change this thread's signal mask to block user-visible signals
396  * (HUP, TERM, QUIT, INT), and store the old signal mask in
397  * *old_set_storage.
398  * Return 0 for success, or -1 if an error occurred.
399  */
400 
401  /*
402   * This does not work in Darwin alias MacOS X alias Mach kernel,
403   * however. So we define a dummy function doing nothing.
404   */
405 #if defined(DARWIN_OLD)
406     static int pthread_sigmask();
407 #endif
408 
block_user_signals(sigset_t * old_set_storage)409 static int block_user_signals(sigset_t *old_set_storage)
410 {
411     int ret;
412     sigset_t block_signals;
413 
414     ret = sigemptyset(&block_signals);
415     if (ret != 0) {
416         error(errno, "gwthread-pthread: Couldn't initialize signal set");
417 	    return -1;
418     }
419     ret = sigaddset(&block_signals, SIGHUP);
420     ret |= sigaddset(&block_signals, SIGTERM);
421     ret |= sigaddset(&block_signals, SIGQUIT);
422     ret |= sigaddset(&block_signals, SIGINT);
423     if (ret != 0) {
424         error(0, "gwthread-pthread: Couldn't add signal to signal set");
425 	    return -1;
426     }
427     ret = pthread_sigmask(SIG_BLOCK, &block_signals, old_set_storage);
428     if (ret != 0) {
429         error(ret,
430             "gwthread-pthread: Couldn't disable signals for thread creation");
431         return -1;
432     }
433     return 0;
434 }
435 
restore_user_signals(sigset_t * old_set)436 static void restore_user_signals(sigset_t *old_set)
437 {
438     int ret;
439 
440     ret = pthread_sigmask(SIG_SETMASK, old_set, NULL);
441     if (ret != 0) {
442         panic(ret, "gwthread-pthread: Couldn't restore signal set.");
443     }
444 }
445 
446 
spawn_thread(gwthread_func_t * func,const char * name,void * arg)447 static long spawn_thread(gwthread_func_t *func, const char *name, void *arg)
448 {
449     int ret;
450     pthread_t id;
451     struct new_thread_args *p = NULL;
452     long new_thread_id;
453 
454     /* We want to pass both these arguments to our wrapper function
455      * new_thread, but the pthread_create interface will only let
456      * us pass one pointer.  So we wrap them in a little struct. */
457     p = gw_malloc(sizeof(*p));
458     p->func = func;
459     p->arg = arg;
460     p->ti = gw_malloc(sizeof(*(p->ti)));
461     p->failed = 0;
462 
463     /* Lock the thread table here, so that new_thread can block
464      * on that lock.  That way, the new thread won't start until
465      * we have entered it in the thread table. */
466     lock();
467 
468     if (active_threads >= THREADTABLE_SIZE) {
469         unlock();
470         warning(0, "Too many threads, could not create new thread.");
471         gw_free(p);
472         return -1;
473     }
474 
475     ret = pthread_create(&id, NULL, &new_thread, p);
476     if (ret != 0) {
477         unlock();
478         error(ret, "Could not create new thread.");
479         gw_free(p);
480         return -1;
481     }
482     ret = pthread_detach(id);
483     if (ret != 0) {
484         error(ret, "Could not detach new thread.");
485     }
486 
487     new_thread_id = fill_threadinfo(id, name, func, p->ti);
488     if (new_thread_id == -1)
489         p->failed = 1;
490     unlock();
491 
492     if (new_thread_id != -1)
493         debug("gwlib.gwthread", 0, "Started thread %ld (%s)", new_thread_id, name);
494     else
495         debug("gwlib.gwthread", 0, "Failed to start thread (%s)", name);
496 
497     return new_thread_id;
498 }
499 
gwthread_create_real(gwthread_func_t * func,const char * name,void * arg)500 long gwthread_create_real(gwthread_func_t *func, const char *name, void *arg)
501 {
502     int sigtrick = 0;
503     sigset_t old_signal_set;
504     long thread_id;
505 
506     /*
507      * We want to make sure that only the main thread handles signals,
508      * so that each signal is handled exactly once.  To do this, we
509      * make sure that each new thread has all the signals that we
510      * handle blocked.  To avoid race conditions, we block them in
511      * the spawning thread first, then create the new thread (which
512      * inherits the settings), and then restore the old settings in
513      * the spawning thread.  This means that there is a brief period
514      * when no signals will be processed, but during that time they
515      * should be queued by the operating system.
516      */
517     if (gwthread_self() == MAIN_THREAD_ID)
518 	    sigtrick = block_user_signals(&old_signal_set) == 0;
519 
520     thread_id = spawn_thread(func, name, arg);
521 
522     /*
523      * Restore the old signal mask.  The new thread will have
524      * inherited the resticted one, but the main thread needs
525      * the old one back.
526      */
527     if (sigtrick)
528  	    restore_user_signals(&old_signal_set);
529 
530     return thread_id;
531 }
532 
gwthread_join(long thread)533 void gwthread_join(long thread)
534 {
535     struct threadinfo *threadinfo;
536     pthread_cond_t exit_cond;
537     int ret;
538 
539     gw_assert(thread >= 0);
540 
541     lock();
542     threadinfo = THREAD(thread);
543     if (threadinfo == NULL || threadinfo->number != thread) {
544         /* The other thread has already exited */
545         unlock();
546         return;
547     }
548 
549     /* Register our desire to be alerted when that thread exits,
550      * and wait for it. */
551 
552     ret = pthread_cond_init(&exit_cond, NULL);
553     if (ret != 0) {
554         warning(ret, "gwthread_join: cannot create condition variable.");
555         unlock();
556         return;
557     }
558 
559     if (!threadinfo->joiners)
560         threadinfo->joiners = gwlist_create();
561     gwlist_append(threadinfo->joiners, &exit_cond);
562 
563     /* The wait immediately releases the lock, and reacquires it
564      * when the condition is satisfied.  So don't worry, we're not
565      * blocking while keeping the table locked. */
566     pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, &threadtable_lock);
567     ret = pthread_cond_wait(&exit_cond, &threadtable_lock);
568     pthread_cleanup_pop(0);
569     unlock();
570 
571     if (ret != 0)
572         warning(ret, "gwthread_join: error in pthread_cond_wait");
573 
574     pthread_cond_destroy(&exit_cond);
575 }
576 
gwthread_join_all(void)577 void gwthread_join_all(void)
578 {
579     long i;
580     long our_thread = gwthread_self();
581 
582     for (i = 0; i < THREADTABLE_SIZE; ++i) {
583         if (THREAD(our_thread) != THREAD(i))
584             gwthread_join(i);
585     }
586 }
587 
gwthread_wakeup_all(void)588 void gwthread_wakeup_all(void)
589 {
590     long i;
591     long our_thread = gwthread_self();
592 
593     for (i = 0; i < THREADTABLE_SIZE; ++i) {
594         if (THREAD(our_thread) != THREAD(i))
595             gwthread_wakeup(i);
596     }
597 }
598 
gwthread_join_every(gwthread_func_t * func)599 void gwthread_join_every(gwthread_func_t *func)
600 {
601     struct threadinfo *ti;
602     pthread_cond_t exit_cond;
603     int ret;
604     long i;
605 
606     ret = pthread_cond_init(&exit_cond, NULL);
607     if (ret != 0) {
608         warning(ret, "gwthread_join_every: cannot create condition variable.");
609         unlock();
610         return;
611     }
612 
613     /*
614      * FIXME: To be really safe, this function should keep looping
615      * over the table until it does a complete run without having
616      * to call pthread_cond_wait.  Otherwise, new threads could
617      * start while we wait, and we'll miss them.
618      */
619     lock();
620     for (i = 0; i < THREADTABLE_SIZE; ++i) {
621         ti = THREAD(i);
622         if (ti == NULL || ti->func != func)
623             continue;
624         debug("gwlib.gwthread", 0,
625               "Waiting for %ld (%s) to terminate",
626               ti->number, ti->name);
627         if (!ti->joiners)
628             ti->joiners = gwlist_create();
629         gwlist_append(ti->joiners, &exit_cond);
630         pthread_cleanup_push((void(*)(void*))pthread_mutex_unlock, &threadtable_lock);
631         ret = pthread_cond_wait(&exit_cond, &threadtable_lock);
632         pthread_cleanup_pop(0);
633         if (ret != 0)
634             warning(ret, "gwthread_join_all: error in pthread_cond_wait");
635     }
636     unlock();
637 
638     pthread_cond_destroy(&exit_cond);
639 }
640 
641 /* Return the thread id of this thread. */
gwthread_self(void)642 long gwthread_self(void)
643 {
644     struct threadinfo *threadinfo;
645     threadinfo = pthread_getspecific(tsd_key);
646     if (threadinfo)
647         return threadinfo->number;
648     else
649         return -1;
650 }
651 
652 /* Return the thread pid of this thread. */
gwthread_self_pid(void)653 long gwthread_self_pid(void)
654 {
655     struct threadinfo *threadinfo;
656     threadinfo = pthread_getspecific(tsd_key);
657     if (threadinfo && threadinfo->pid != -1)
658         return (long) threadinfo->pid;
659     else
660         return (long) getpid();
661 }
662 
gwthread_self_ids(long * tid,long * pid)663 void gwthread_self_ids(long *tid, long *pid)
664 {
665     struct threadinfo *threadinfo;
666     threadinfo = pthread_getspecific(tsd_key);
667     if (threadinfo) {
668         *tid = threadinfo->number;
669         *pid = (threadinfo->pid != -1) ? threadinfo->pid : getpid();
670     } else {
671         *tid = -1;
672         *pid = getpid();
673     }
674 }
675 
gwthread_wakeup(long thread)676 void gwthread_wakeup(long thread)
677 {
678     unsigned char c = 0;
679     struct threadinfo *threadinfo;
680     int fd;
681 
682     gw_assert(thread >= 0);
683 
684     lock();
685 
686     threadinfo = THREAD(thread);
687     if (threadinfo == NULL || threadinfo->number != thread) {
688         unlock();
689         return;
690     }
691 
692     fd = threadinfo->wakefd_send;
693     unlock();
694 
695     write(fd, &c, 1);
696 }
697 
gwthread_pollfd(int fd,int events,double timeout)698 int gwthread_pollfd(int fd, int events, double timeout)
699 {
700     struct pollfd pollfd[2];
701     struct threadinfo *threadinfo;
702     int milliseconds;
703     int ret;
704 
705     threadinfo = getthreadinfo();
706 
707     pollfd[0].fd = threadinfo->wakefd_recv;
708     pollfd[0].events = POLLIN;
709     pollfd[0].revents = 0;
710 
711     pollfd[1].fd = fd;
712     pollfd[1].events = events;
713     pollfd[1].revents = 0;
714 
715     milliseconds = timeout * 1000;
716     if (milliseconds < 0)
717         milliseconds = POLL_NOTIMEOUT;
718 
719     ret = poll(pollfd, 2, milliseconds);
720     if (ret < 0) {
721         if (errno != EINTR)
722             error(errno, "gwthread_pollfd: error in poll");
723         return -1;
724     }
725 
726     if (pollfd[0].revents)
727         flushpipe(pollfd[0].fd);
728 
729     return pollfd[1].revents;
730 }
731 
gwthread_poll(struct pollfd * fds,long numfds,double timeout)732 int gwthread_poll(struct pollfd *fds, long numfds, double timeout)
733 {
734     struct pollfd *pollfds;
735     struct threadinfo *threadinfo;
736     int milliseconds;
737     int ret;
738 
739     threadinfo = getthreadinfo();
740 
741     /* Create a new pollfd array with an extra element for the
742      * thread wakeup fd. */
743 
744     pollfds = gw_malloc((numfds + 1) * sizeof(*pollfds));
745     pollfds[0].fd = threadinfo->wakefd_recv;
746     pollfds[0].events = POLLIN;
747     pollfds[0].revents = 0;
748     memcpy(pollfds + 1, fds, numfds * sizeof(*pollfds));
749 
750     milliseconds = timeout * 1000;
751     if (milliseconds < 0)
752         milliseconds = POLL_NOTIMEOUT;
753 
754     ret = poll(pollfds, numfds + 1, milliseconds);
755     if (ret < 0) {
756         if (errno != EINTR)
757             error(errno, "gwthread_poll: error in poll");
758         gw_free(pollfds);
759         return -1;
760     }
761     if (pollfds[0].revents)
762         flushpipe(pollfds[0].fd);
763 
764     /* Copy the results back to the caller */
765     memcpy(fds, pollfds + 1, numfds * sizeof(*pollfds));
766     gw_free(pollfds);
767 
768     return ret;
769 }
770 
771 
gwthread_sleep(double seconds)772 void gwthread_sleep(double seconds)
773 {
774     struct pollfd pollfd;
775     struct threadinfo *threadinfo;
776     int milliseconds;
777     int ret;
778 
779     threadinfo = getthreadinfo();
780 
781     pollfd.fd = threadinfo->wakefd_recv;
782     pollfd.events = POLLIN;
783 
784     milliseconds = seconds * 1000;
785     if (milliseconds < 0)
786         milliseconds = POLL_NOTIMEOUT;
787 
788     ret = poll(&pollfd, 1, milliseconds);
789     if (ret < 0) {
790         if (errno != EINTR && errno != EAGAIN) {
791             warning(errno, "gwthread_sleep: error in poll");
792         }
793     }
794     if (ret == 1) {
795         flushpipe(pollfd.fd);
796     }
797 }
798 
799 
gwthread_sleep_micro(double dseconds)800 void gwthread_sleep_micro(double dseconds)
801 {
802     fd_set fd_set_recv;
803     struct threadinfo *threadinfo;
804     int fd;
805     int ret;
806 
807     threadinfo = getthreadinfo();
808     fd = threadinfo->wakefd_recv;
809 
810     FD_ZERO(&fd_set_recv);
811     FD_SET(fd, &fd_set_recv);
812 
813     if (dseconds < 0) {
814         ret = select(fd + 1, &fd_set_recv, NULL, NULL, NULL);
815     } else {
816         struct timeval timeout;
817         timeout.tv_sec = dseconds;
818         timeout.tv_usec = (dseconds - timeout.tv_sec) * 1000000;
819 
820         ret = select(fd + 1, &fd_set_recv, NULL, NULL, &timeout);
821     }
822 
823     if (ret < 0) {
824         if (errno != EINTR && errno != EAGAIN) {
825             warning(errno, "gwthread_sleep_micro: error in select()");
826         }
827     }
828 
829     if (FD_ISSET(fd, &fd_set_recv)) {
830         flushpipe(fd);
831     }
832 }
833 
834 
gwthread_cancel(long thread)835 int gwthread_cancel(long thread)
836 {
837     struct threadinfo *threadinfo;
838     int ret;
839 
840     gw_assert(thread >= 0);
841 
842     lock();
843     threadinfo = THREAD(thread);
844     if (threadinfo == NULL || threadinfo->number != thread) {
845         ret = -1;
846     } else {
847         ret = pthread_cancel(threadinfo->self);
848         debug("gwlib.gwthread", 0, "Thread %ld (%s) canceled.",
849               threadinfo->number, threadinfo->name);
850     }
851     unlock();
852     return ret;
853 }
854 
855 
856 #ifndef BROKEN_PTHREADS
857 
858 /* Working pthreads */
gwthread_shouldhandlesignal(int signal)859 int gwthread_shouldhandlesignal(int signal){
860     return 1;
861 }
862 #else
863 
864 /* Somewhat broken pthreads */
gwthread_shouldhandlesignal(int signal)865 int gwthread_shouldhandlesignal(int signal){
866     return (gwthread_self() == MAIN_THREAD_ID);
867 }
868 #endif
869 
gwthread_dumpsigmask(void)870 int gwthread_dumpsigmask(void) {
871     sigset_t signal_set;
872     int signum;
873 
874     /* Grab the signal set data from our thread */
875     if (pthread_sigmask(SIG_BLOCK, NULL, &signal_set) != 0) {
876 	    warning(0, "gwthread_dumpsigmask: Couldn't get signal mask.");
877 	    return -1;
878     }
879 
880     /* For each signal normally defined (there are usually only 32),
881      * print a message if we don't block it. */
882     for (signum = 1; signum <= 32; signum++) {
883 	     if (!sigismember(&signal_set, signum)) {
884 	         debug("gwlib", 0,
885 		     "gwthread_dumpsigmask: Signal Number %d will be caught.",
886 		     signum);
887 	     }
888     }
889     return 0;
890 }
891 
892 /* DARWIN alias MacOS X doesnt have pthread_sigmask in its pthreads implementation */
893 
894 #if defined(DARWIN_OLD)
pthread_sigmask()895 static int pthread_sigmask()
896 {
897     return 0;
898 }
899 #endif
900