static void *new_thread(void *arg) { int ret; struct new_thread_args *p = arg; /* Make sure we don't start until our parent has entered * our thread info in the thread table. */ lock(); /* check for initialization errors */ if (p->failed) { /* Must free p before signaling our exit, otherwise there is * a race with gw_check_leaks at shutdown. */ gw_free(p); delete_threadinfo(); unlock(); return NULL; } unlock(); /* This has to be done here, because pthread_setspecific cannot * be called by our parent on our behalf. That's why the ti * pointer is passed in the new_thread_args structure. */ /* Synchronization is not a problem, because the only thread * that relies on this call having been made is this one -- * no other thread can access our TSD anyway. */ ret = pthread_setspecific(tsd_key, p->ti); if (ret != 0) { panic(ret, "gwthread-pthread: pthread_setspecific failed"); } p->ti->pid = getpid(); debug("gwlib.gwthread", 0, "Thread %ld (%s) maps to pid %ld.", p->ti->number, p->ti->name, (long) p->ti->pid); (p->func)(p->arg); lock(); debug("gwlib.gwthread", 0, "Thread %ld (%s) terminates.", p->ti->number, p->ti->name); alert_joiners(); #ifdef HAVE_LIBSSL /* Clear the OpenSSL thread-specific error queue to avoid * memory leaks. */ ERR_remove_state(gwthread_self()); #endif /* HAVE_LIBSSL */ /* Must free p before signaling our exit, otherwise there is * a race with gw_check_leaks at shutdown. */ gw_free(p); delete_threadinfo(); unlock(); return NULL; }
static void *new_thread(void *arg) { int ret; struct new_thread_args *p = arg; /* Make sure we don't start until our parent has entered * our thread info in the thread table. */ lock(); /* check for initialization errors */ if (p->failed) { /* Must free p before signaling our exit, otherwise there is * a race with gw_check_leaks at shutdown. */ gw_free(p); delete_threadinfo(); unlock(); return NULL; } unlock(); /* This has to be done here, because pthread_setspecific cannot * be called by our parent on our behalf. That's why the ti * pointer is passed in the new_thread_args structure. */ /* Synchronization is not a problem, because the only thread * that relies on this call having been made is this one -- * no other thread can access our TSD anyway. */ ret = pthread_setspecific(tsd_key, p->ti); if (ret != 0) { panic(ret, "gwthread-pthread: pthread_setspecific failed"); } p->ti->pid = getpid(); debug("gwlib.gwthread", 0, "Thread %ld (%s) maps to pid %ld.", p->ti->number, p->ti->name, (long) p->ti->pid); /* set cancel cleanup function */ pthread_cleanup_push(new_thread_cleanup, p); (p->func)(p->arg); pthread_cleanup_pop(0); new_thread_cleanup(p); return NULL; }
static void new_thread_cleanup(void *arg) { struct new_thread_args *p = arg; lock(); debug("gwlib.gwthread", 0, "Thread %ld (%s) terminates.", p->ti->number, p->ti->name); alert_joiners(); #ifdef HAVE_LIBSSL /* Clear the OpenSSL thread-specific error queue to avoid * memory leaks. */ ERR_remove_state(gwthread_self()); #endif /* HAVE_LIBSSL */ /* Must free p before signaling our exit, otherwise there is * a race with gw_check_leaks at shutdown. */ gw_free(p); delete_threadinfo(); unlock(); }