int ldap_int_thread_destroy( void ) { #ifdef HAVE_PTHREAD_KILL_OTHER_THREADS_NP /* LinuxThreads: kill clones */ pthread_kill_other_threads_np(); #endif LDAP_ENSURE( pthread_mutexattr_destroy( &mutex_attr_errorcheck ) == 0); return 0; }
int ldap_int_thread_destroy( void ) { #ifdef HAVE_PTHREAD_KILL_OTHER_THREADS_NP /* LinuxThreads: kill clones */ pthread_kill_other_threads_np(); #endif #ifdef LDAP_INT_THREAD_MUTEXATTR pthread_mutexattr_destroy( &mutex_attr ); #endif return 0; }
static void xkb_free(Control *ctrl) { terminate(); pthread_kill_other_threads_np(); deinitialize_xkb(); t_xkb *xkb; g_return_if_fail(ctrl != NULL); g_return_if_fail(ctrl->data != NULL); xkb = (t_xkb *)ctrl->data; g_free(xkb); }
/** * Kill all other threads. * * THREADS: MT-SAFE * * This should be called prior to any call to exit/exec, and is abused by * bk_general_destroy to prevent concurrent access to bk_general by terminating * rival threads with extreme prejudice. * * @param B BAKA Thread/global state * @param flags Flags for the future (avoid pthread_kill_other_threads_np()?) */ void bk_thread_kill_others(bk_s B, bk_flags flags) { BK_ENTRY_VOLATILE(B, __FUNCTION__, __FILE__, "libbk"); #ifdef HAVE_PTHREAD_KILL_OTHER_THREADS_NP /* * <WARNING bugid="1281"> * Using pthread_kill_other_threads_np is only necessary on Linux (or any * platform that doesn't comply with the POSIX requirement that exec/exit * terminate all threads - fortunately, Linux is unique in that respect). * * Even on Linux, this should really be called *after* iterating through the * thread list, not *instead of*, since it prevents thread cancellation * handlers cancellation etc. etc. but I just want to compile on *BSD without * giving anyone a "false sense of security." So we'll let the users on *BSD * find out if this code works, unless a Linux user hangs first because of a * mutex held by another thread killed by pthread_kill_other_threads_np. * </WARNING> */ pthread_kill_other_threads_np(); #else /* HAVE_PTHREAD_KILL_OTHER_THREADS_NP */ struct bk_threadlist * volatile tlist; struct bk_threadnode *tnode; dict_iter iter; if ((tlist = BK_GENERAL_TLIST(B))) { /* * <TRICKY>If multiple threads call this at the same time, we need to * make sure that only one of them cancels the other threads; all the * others should be cancelled by the one that won the race. * * We do this by checking for cancellation once tlist->btl_lock is held; * the cleanup handler makes sure that this thread will release the lock if * it lost the race and was cancelled.</TRICKY> */ if (pthread_mutex_lock(&tlist->btl_lock)) abort(); pthread_cleanup_push(bk_thread_unlock, &tlist->btl_lock); pthread_testcancel(); pthread_cleanup_pop(0); // don't unlock yet iter = btl_iterate(tlist->btl_list, DICT_FROM_START); while ((tnode = btl_nextobj(tlist->btl_list, iter))) { if (BK_FLAG_ISCLEAR(tnode->btn_flags, BK_THREADNODE_FLAG_CANCELED) && !pthread_equal(tnode->btn_thid, pthread_self())) { bk_thread_cancel(B, tnode->btn_thid, 0); } } btl_iterate_done(tlist->btl_list, iter); /* * We have cancelled all existing baka threads; now we have to wait for * them to reach cancellation points and take themselves off the thread * list. (No new threads should be created, since bk_thread_create has a * cancellation point that will prevent it from creating a new thread if * the existing one is cancelled). */ do { tnode = btl_minimum(tlist->btl_list); // is this thread the only one on the list? if (!tnode || (pthread_equal(tnode->btn_thid, pthread_self()) && !(btl_successor(tlist->btl_list, tnode)))) break; // not yet - wait and see if (pthread_cond_wait(&tlist->btl_cv, &tlist->btl_lock)) abort(); } while (1); if (pthread_mutex_unlock(&tlist->btl_lock)) abort(); } #endif /* HAVE_PTHREAD_KILL_OTHER_THREADS_NP */ BK_VRETURN(B); }
// this function is waste, DON'T USE it void kill_all_timer() { pthread_kill_other_threads_np(); };
void rerunDaemon() { #ifndef WIN32 #ifdef OW_HAVE_PTHREAD_KILL_OTHER_THREADS_NP // do this, since it seems that on some distros (debian sarge for instance) // it doesn't happen when calling execv(), and it shouldn't hurt if it's // called twice. pthread_kill_other_threads_np(); #endif #ifdef OW_DARWIN // On Darwin, execv() fails with a ENOTIMP if any threads are running. // The only way we have to really get rid of all the threads is to call fork() and exit() the parent. // Note that we don't do this on other platforms because fork() isn't safe to call from a signal handler, and isn't necessary. if (::fork() != 0) { _exit(1); // if fork fails or we're the parent, just exit. } // child continues. #endif // On Linux pthreads will kill off all the threads when we call // execv(). If we close all the fds, then that breaks pthreads and // execv() will just hang. // Instead set the close on exec flag so all file descriptors are closed // by the kernel when we evecv() and we won't leak them. rlimit rl; int i = sysconf(_SC_OPEN_MAX); if (getrlimit(RLIMIT_NOFILE, &rl) != -1) { if ( i < 0 ) { i = rl.rlim_max; } else { i = std::min<int>(rl.rlim_max, i); } } struct flock lck; ::memset (&lck, '\0', sizeof (lck)); lck.l_type = F_UNLCK; // unlock lck.l_whence = 0; // 0 offset for l_start lck.l_start = 0L; // lock starts at BOF lck.l_len = 0L; // extent is entire file while (i > 2) { // clear any file locks - this shouldn't technically be necessary, but it seems on some systems, even though we restart, the locks persist, // either because of bugs in the kernel or somehow things still hang around... ::fcntl(i, F_SETLK, &lck); // set it for close on exec ::fcntl(i, F_SETFD, FD_CLOEXEC); i--; } // reset the signal mask, since that is inherited by an exec()'d process, and if // this was called from a signal handler, the signal being handled (e.g. SIGSEGV) will be blocked. // some platforms make macros for sigemptyset, so we can't use :: sigset_t emptymask; sigemptyset(&emptymask); ::sigprocmask(SIG_SETMASK, &emptymask, 0); #endif // This doesn't return. execv() will replace the current process with a // new copy of g_argv[0] (owcimomd). ::execv(g_argv[0], g_argv); // If we get here we're pretty much hosed. OW_THROW_ERRNO_MSG(DaemonException, "execv() failed"); }