int ldap_thr_index() { int i = 0; int free = 0; pthread_t cur = thr_self(); for (i = 1; i < MAX_THREAD_ID; ++i) { if (ldap_thr_table[i] == cur) { return (i); } /* end if */ } /* end for */ /* * not in the table, allocate a new entry */ pthread_mutex_lock(&ldap_thr_index_mutex); for (i = 1; i < MAX_THREAD_ID; ++i) { if (ldap_thr_table[i] == 0 || thr_kill(ldap_thr_table[i], 0) != 0) { ldap_thr_table[i] = cur; pthread_mutex_unlock(&ldap_thr_index_mutex); return (i); } /* end if */ } /* end for */ pthread_mutex_unlock(&ldap_thr_index_mutex); /* if table is full, return the first entry, so that it */ /* doesn't core dump */ return (0); }
/**************************************************************************** * Read messages from the server. ****************************************************************************/ void *ReaderThread(void *arg) { ReaderData *data = arg; Message msg; for(;;) { printf("\x1B[1;37;40m\n"); read(data->sd, &msg, sizeof(msg)); switch(msg.control) { case CONTROL_MSG: printf("\x1B[1;32;40m"); printf("\n%s@%s: %s", msg.name, msg.host, msg.message); break; case CONTROL_LOGIN: printf("\x1B[1;33;40m"); printf("\n*** %s@%s has logged in.", msg.name, msg.host); break; case CONTROL_LOGOUT: printf("\x1B[1;34;40m"); printf("\n*** %s@%s has logged out.", msg.name, msg.host); break; case CONTROL_TERM: printf("\x1B[1;31;40m"); printf("\nServer is shutting down, exiting."); close(data->sd); thr_kill(data->parent, SIGINT); printf("\x1B[0m\n"); exit(0); break; default: printf("\nInvalid response from server.\n"); break; } } }
void solarisSyncInterruptWait(CVMThreadID *thread) { int kill_status; /* NOTE: Maybe we should wake up all waiters using broadcast instead? */ kill_status = thr_kill(SOLARIS_COOKIE(thread), SIGUSR2); assert(kill_status == 0); }
/* signal all clients that console has been deleted */ boolean_t vntsd_notify_client_cons_del(vntsd_client_t *clientp) { (void) mutex_lock(&clientp->lock); clientp->status |= VNTSD_CLIENT_CONS_DELETED; (void) thr_kill(clientp->cons_tid, SIGUSR1); (void) mutex_unlock(&clientp->lock); return (B_FALSE); }
// Stop and destroy the frame thread, wait up to 1/2 second for audio to finish int HAE_DestroyFrameThread(void* context) { if (theFrameThread) { thr_kill(theFrameThread, 0); theFrameThread = NULL; theFrameProc = NULL; return 0; } DEBUG_STR("PV_NativeFrameThreadProc() called when no thread started\n"); return -1; }
void kill_off_threads(library_t *library) { int i; for (i = 0; i < SONY_MAIN_THREADS; i++) if (threads[i] > 0) if (thr_kill(threads[i], SIGKILL) && DBG_LVL(SAM_DBG_DEBUG)) sam_syslog(LOG_INFO, "kill_off_threads: Unable to kill" " thread %d.\n", i); }
/****************************************************************** * KpThreadTerminate (Solaris Version) * * Description * * This function causes the thread specified by thread to be terminated. * * The exitCode argument is ignored for this version * * Author * mjb * * Created * July 5, 1994 *****************************************************************************/ KpInt32_t KpThreadTerminate (KpThread_t thread, KpInt32_t exitCode) { int retVal; exitCode = 0; /* eliminate compiler warning */ retVal = thr_kill (thread, SIGKILL); if (0 != retVal) { return (KCMS_FAIL); } return (KCMS_SUCCESS); } /* KpThreadTerminate */
JNIEXPORT void JNICALL Java_sun_nio_ch_NativeThread_signal(JNIEnv *env, jclass cl, jlong thread) { int ret; #ifdef __solaris__ ret = thr_kill((thread_t)thread, INTERRUPT_SIGNAL); #else ret = pthread_kill((pthread_t)thread, INTERRUPT_SIGNAL); #endif #ifdef MACOSX if (ret != 0 && ret != ESRCH) #else if (ret != 0) #endif JNU_ThrowIOExceptionWithLastError(env, "Thread signal failed"); }
// Called by the requesting thread to send a signal to target thread and // execute "this" callback from the signal handler. int OSThread::Sync_Interrupt_Callback::interrupt(Thread * target, int timeout) { // Let signals to the vm_thread go even if the Threads_lock is not acquired assert(Threads_lock->owned_by_self() || (target == VMThread::vm_thread()), "must have threads lock to call this"); OSThread * osthread = target->osthread(); // may block if target thread already has a pending callback osthread->set_interrupt_callback(this); _target = target; int rslt = thr_kill(osthread->thread_id(), os::Solaris::SIGasync()); assert(rslt == 0, "thr_kill != 0"); bool status = false; jlong t1 = os::javaTimeMillis(); { // don't use safepoint check because we might be the watcher thread. MutexLockerEx ml(_sync, Mutex::_no_safepoint_check_flag); while (!is_done()) { status = _sync->wait(Mutex::_no_safepoint_check_flag, timeout); // status == true if timed out if (status) break; // update timeout jlong t2 = os::javaTimeMillis(); timeout -= t2 - t1; t1 = t2; } } // reset current_callback osthread->remove_interrupt_callback(this); return status; }
/* * all clients connected to a console must disconnect before * removing a console. */ static void cleanup_cons(vntsd_cons_t *consp) { vntsd_group_t *groupp; timestruc_t to; assert(consp); D1(stderr, "t@%d vntsd_disconn_clients@%d\n", thr_self(), consp->cons_no); groupp = consp->group; assert(groupp); (void) mutex_lock(&consp->lock); /* wait for all clients disconnect from the console */ while (consp->clientpq != NULL) { consp->status |= VNTSD_CONS_SIG_WAIT; /* signal client to disconnect the console */ (void) vntsd_que_walk(consp->clientpq, (el_func_t)vntsd_notify_client_cons_del); (void) thr_kill(consp->wr_tid, SIGUSR1); to.tv_sec = VNTSD_CV_WAIT_DELTIME; to.tv_nsec = 0; /* wait for clients to disconnect */ (void) cond_reltimedwait(&consp->cvp, &consp->lock, &to); } (void) mutex_unlock(&consp->lock); free_cons(consp); }
/**************************************************************************** * Main entry point. ****************************************************************************/ int main(int argc, char *argv[]) { ReaderData data; int sd; int temp; int x; struct sockaddr_in server_addr = { AF_INET, htons(SERVER_PORT) }; struct hostent *hp; Message msg; printf("\x1B[1;37;40m"); signal(SIGALRM, SIG_IGN); if(argc != 3) { printf("usage: %s nickname hostname\n", argv[0]); exit(1); } if((hp = gethostbyname(argv[2])) == NULL) { printf("%s: error: %s unknown host\n", argv[0], argv[2]); exit(1); } bcopy(hp->h_addr_list[0], (char*)&server_addr.sin_addr, hp->h_length); /* Create a socket */ if((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("%s: error: socket failed\n", argv[0]); exit(1); } /* Connect to the server */ if(connect(sd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) { printf("%s: error: could not connect to host\n", argv[0]); exit(1); } printf("Connected to %s\n", argv[2]); printf("Type \"exit\" to quit.\n"); gethostname(msg.host, HOST_LENGTH); strncpy(msg.name, argv[1], NAME_LENGTH); write(sd, msg, sizeof(msg)); data.sd = sd; data.parent = thr_self(); thr_create(0, 0, ReaderThread, &data, 0, &tid); /* Wait for user input */ do { for(x = 0; x < MAX_BUFFER; x++) { temp = getc(stdin); if(temp == '\n') { break; } msg.message[x] = temp; } msg.message[x] = 0; msg.control = CONTROL_MSG; write(sd, msg, sizeof(msg)); } while(x != 4 || strncmp(msg.message, "exit", 4)); thr_kill(tid, SIGINT); msg.control = CONTROL_LOGOUT; write(sd, msg, sizeof(msg)); close(sd); printf("\x1B[0m\n"); exit(0); }
/* * check the state of listen thread. exit if there is an fatal error * or the group is removed. Main thread will call free_group * to close group socket and free group structure. */ static void listen_chk_status(vntsd_group_t *groupp, int status) { char err_msg[VNTSD_LINE_LEN]; D1(stderr, "t@%d listen_chk_status() status=%d group=%s " "tcp=%lld group status = %x\n", thr_self(), status, groupp->group_name, groupp->tcp_port, groupp->status); (void) snprintf(err_msg, sizeof (err_msg), "Group:%s TCP port %lld status %x", groupp->group_name, groupp->tcp_port, groupp->status); switch (status) { case VNTSD_SUCCESS: return; case VNTSD_STATUS_ACCEPT_ERR: return; case VNTSD_STATUS_INTR: assert(groupp->status & VNTSD_GROUP_SIG_WAIT); /*FALLTHRU*/ case VNTSD_STATUS_NO_CONS: default: /* fatal error or no console in the group, remove the group. */ (void) mutex_lock(&groupp->lock); if (groupp->status & VNTSD_GROUP_SIG_WAIT) { /* * group is already being deleted, notify main * thread and exit. */ groupp->status &= ~VNTSD_GROUP_SIG_WAIT; (void) cond_signal(&groupp->cvp); (void) mutex_unlock(&groupp->lock); thr_exit(0); } /* * if there still is console(s) in the group, * the console(s) could not be connected any more because of * a fatal error. Therefore, mark the console and notify * main thread to delete console and group. */ (void) vntsd_que_walk(groupp->conspq, (el_func_t)vntsd_mark_deleted_cons); groupp->status |= VNTSD_GROUP_CLEAN_CONS; /* signal main thread to delete the group */ (void) thr_kill(groupp->vntsd->tid, SIGUSR1); (void) mutex_unlock(&groupp->lock); /* log error */ if (status != VNTSD_STATUS_NO_CONS) vntsd_log(status, err_msg); thr_exit(0); } }
int _thr_send_sig(struct pthread *thread, int sig) { return thr_kill(thread->tid, sig); }
/* * fscache_simdisconnect * * Description: * Simulates disconnection or reconnects from a simulated disconnection. * Arguments: * disconnect 1 means disconnect, !1 means connect * Returns: * Returns 0 for success, !0 on an error * Preconditions: */ int fscache_simdisconnect(cfsd_fscache_object_t *fscache_object_p, int disconnect) { int xx; int ret = 0; char *strp; int tcon; int trec; dbug_enter("fscache_simdisconnect"); dbug_precond(fscache_object_p); strp = disconnect ? "disconnection" : "reconnection"; dbug_print(("simdis", "About to simulate %s", strp)); fscache_lock(fscache_object_p); if (disconnect) { /* if file system cannot be disconnected */ if (fscache_object_p->i_disconnectable == 0) { ret = 1; goto out; } /* if file system is already disconnected */ if (fscache_object_p->i_connected == 0) { ret = 2; goto out; } fscache_object_p->i_simdis = 1; } else { /* if file system is already connected */ if (fscache_object_p->i_connected) { ret = 1; goto out; } /* if file system is not "simulated" disconnected */ if (fscache_object_p->i_simdis == 0) { ret = 2; goto out; } fscache_object_p->i_simdis = 0; } /* if fs thread not running */ if (fscache_object_p->i_threaded == 0) { if (fscache_object_p->i_mounted) { dbug_print(("simdis", "thread not running")); ret = -1; } else { if (fscache_object_p->i_simdis) fscache_object_p->i_connected = 0; else fscache_object_p->i_connected = 1; } goto out; } /* get the attention of the thread */ dbug_print(("info", "thread %d, killing %d with sigusr1", thr_self(), fscache_object_p->i_threadid)); xx = thr_kill(fscache_object_p->i_threadid, SIGUSR1); if (xx) { dbug_print(("simdis", "thr_kill failed %d, threadid %d", xx, fscache_object_p->i_threadid)); ret = -1; } out: fscache_unlock(fscache_object_p); if (ret == 0) { for (;;) { dbug_print(("simdis", " waiting for simulated %s", strp)); fscache_lock(fscache_object_p); tcon = fscache_object_p->i_connected; trec = fscache_object_p->i_reconcile; fscache_unlock(fscache_object_p); if (disconnect) { if (tcon == 0) break; } else { if ((tcon == 1) && (trec == 0)) break; } cfsd_sleep(1); } dbug_print(("simdis", "DONE waiting for simulated %s", strp)); } else { dbug_print(("simdis", "simulated %s failed %d", strp, ret)); } dbug_leave("fscache_simdisconnect"); return (ret); }
int ldap_pvt_thread_kill( ldap_pvt_thread_t thread, int signo ) { thr_kill( thread, signo ); return 0; }
int fscache_unmount(cfsd_fscache_object_t *fscache_object_p, int flag) { int xx; int ret = 0; dbug_enter("fscache_unmount"); dbug_precond(fscache_object_p); fscache_lock(fscache_object_p); /* if there is a thread running */ if (fscache_object_p->i_threaded) { /* do not bother unmounting if rolling the log */ if (fscache_object_p->i_reconcile) { ret = EBUSY; goto out; } /* inform the thread to try the unmount */ fscache_object_p->i_tryunmount = 1; fscache_object_p->i_modify++; /* get the attention of the thread */ dbug_print(("info", "about to do umount kill")); xx = thr_kill(fscache_object_p->i_threadid, SIGUSR1); if (xx) { dbug_print(("error", "thr_kill failed %d, threadid %d", xx, fscache_object_p->i_threadid)); ret = EIO; goto out; } /* wait for the thread to wake us up */ while (fscache_object_p->i_tryunmount) { xx = cond_wait(&fscache_object_p->i_cvwait, &fscache_object_p->i_lock); dbug_print(("info", "cond_wait woke up %d %d", xx, fscache_object_p->i_tryunmount)); } /* if the file system is still mounted */ if (fscache_object_p->i_mounted) ret = EBUSY; } /* else if there is no thread running */ else { /* try to unmount the file system */ if (umount2(fscache_object_p->i_mntpt, flag) == -1) { xx = errno; dbug_print(("info", "unmount failed %s", strerror(xx))); if (xx == EBUSY) ret = EBUSY; else if (xx == ENOTSUP) ret = ENOTSUP; else ret = EIO; } else { fscache_object_p->i_mounted = 0; fscache_object_p->i_modify++; } } out: fscache_unlock(fscache_object_p); dbug_leave("fscache_unmount"); return (ret); }
/* * XXX: a bug still exists here. we have a thread polling on this * XXX: device in the kernel, we need to get rid of this also. * XXX: since we're going to move the waiter thread up to the * XXX: user level, it'll be easier to kill off as part of the * XXX: cleanup of the device private data. */ static void rmscsi_close(char *path, dev_t rdev) { char namebuf[MAXNAMELEN]; struct stat sb; struct devs *dp; struct rmscsi_priv *rsp; int i; debug(1, "rmscsi_close %s\n", path); (void) sprintf(namebuf, RMSCSI_NAMEPROTO, path, RMSCSI_BASEPART); if (stat(namebuf, &sb) < 0) { if (rdev == NODEV) { warning(gettext("rmscsi_close: %s; %m\n"), namebuf); return; } } else { rdev = sb.st_rdev; } if ((dp = dev_getdp(rdev)) == NULL) { debug(1, "rmscsi_close: %s not in use\n", path); return; } /* get our private data */ rsp = (struct rmscsi_priv *)dp->dp_priv; /* * take care of the listner thread */ (void) mutex_lock(&rsp->rs_killmutex); (void) thr_kill(rsp->rs_tid, SIGUSR1); (void) mutex_unlock(&rsp->rs_killmutex); (void) thr_join(rsp->rs_tid, 0, 0); debug(1, "rmscsi_close: thread id %d reaped (killed/joined)\n", rsp->rs_tid); /* * if there is a volume inserted in this device ... */ if (dp->dp_vol) { /* * clean up the name space and the device maps * to remove references to any volume that might * be in the device right now * * this crap with the flags is to keep the * "poll" from being relaunched by this function * * yes, its a hack and there should be a better way */ if (dp->dp_dsw->d_flags & D_POLL) { dp->dp_dsw->d_flags &= ~D_POLL; dev_eject(dp->dp_vol, TRUE); dp->dp_dsw->d_flags |= D_POLL; } else { dev_eject(dp->dp_vol, TRUE); } if (dp->dp_vol != NULL) { return; } /* do the eject work */ (void) ioctl(rsp->rs_fd[RMSCSI_BASEPART], DKIOCEJECT, 0); } /* * clean up the names in the name space */ node_unlink(dp->dp_bvn); node_unlink(dp->dp_rvn); /* * free the private data we've allocated */ for (i = 0; i < V_NUMPAR; i++) { if (rsp->rs_rawpath[i]) { free(rsp->rs_rawpath[i]); } if (rsp->rs_fd[i] != -1) { (void) close(rsp->rs_fd[i]); } } #if defined(_FIRMWARE_NEEDS_FDISK) for (i = 0; i < (FD_NUMPART+1); i++) { if (rsp->rs_raw_pfd[i] >= 0) { (void) close(rsp->rs_raw_pfd[i]); } } #endif free(rsp); /* * free the dp, so no one points at us anymore */ dev_freedp(dp); }
int main(int argc, char **argv) { int what_signal, i; char *ent_pnt = "main"; char logname[20]; char *l_mess, *lc_mess; sigset_t sigwait_set; struct sigaction sig_action; dev_ptr_tbl_t *dev_ptr_tbl; shm_ptr_tbl_t *shm_ptr_tbl; sam_defaults_t *defaults; if (argc != 4) exit(1); initialize_fatal_trap_processing(SOLARIS_THREADS, fatal_cleanup); CustmsgInit(1, NULL); library = (library_t *)malloc_wait(sizeof (library_t), 2, 0); (void) memset(library, 0, sizeof (library_t)); /* * Crack the arguments */ argv++; master_shm.shmid = atoi(*argv); argv++; preview_shm.shmid = atoi(*argv); argv++; library->eq = atoi(*argv); mypid = getpid(); if ((master_shm.shared_memory = shmat(master_shm.shmid, NULL, 0774)) == (void *)-1) exit(2); shm_ptr_tbl = (shm_ptr_tbl_t *)master_shm.shared_memory; if ((preview_shm.shared_memory = shmat(preview_shm.shmid, NULL, 0774)) == (void *)-1) exit(3); fifo_path = strdup(SHM_REF_ADDR(shm_ptr_tbl->fifo_path)); sprintf(logname, "sony-%d", library->eq); defaults = GetDefaults(); openlog(logname, LOG_PID | LOG_NOWAIT, defaults->log_facility); dev_ptr_tbl = (dev_ptr_tbl_t *)SHM_REF_ADDR( ((shm_ptr_tbl_t *)master_shm.shared_memory)->dev_table); /* LINTED pointer cast may result in improper alignment */ library->un = (dev_ent_t *) SHM_REF_ADDR(dev_ptr_tbl->d_ent[library->eq]); /* LINTED pointer cast may result in improper alignment */ library->help_msg = (sony_priv_mess_t *) SHM_REF_ADDR(library->un->dt.rb.private); l_mess = library->un->dis_mes[DIS_MES_NORM]; lc_mess = library->un->dis_mes[DIS_MES_CRIT]; /* check if we should log sef data */ (void) sef_status(); if (DBG_LVL(SAM_DBG_RBDELAY)) { int ldk = 60; sam_syslog(LOG_DEBUG, "Waiting for 60 seconds."); while (ldk > 0 && DBG_LVL(SAM_DBG_RBDELAY)) { sprintf(lc_mess, "waiting for %d seconds pid %d", ldk, mypid); sleep(10); ldk -= 10; } *lc_mess = '\0'; } mutex_init(&library->mutex, USYNC_THREAD, NULL); /* * Hold the lock until initialization is complete */ mutex_lock(&library->mutex); common_init(library->un); mutex_init(&library->help_msg->mutex, USYNC_PROCESS, NULL); cond_init(&library->help_msg->cond_i, USYNC_PROCESS, NULL); cond_init(&library->help_msg->cond_r, USYNC_PROCESS, NULL); library->help_msg->mtype = SONY_PRIV_VOID; /* * Start the main threads */ if (thr_create(NULL, DF_THR_STK, monitor_msg, (void *)library, (THR_BOUND | THR_NEW_LWP | THR_DETACHED), &threads[SONY_MSG_THREAD])) { sam_syslog(LOG_ERR, "Unable to start thread monitor_msg: %m.\n"); thr_exit(NULL); } if (thr_create(NULL, MD_THR_STK, manage_list, (void *)library, (THR_BOUND |THR_NEW_LWP | THR_DETACHED), &threads[SONY_WORK_THREAD])) { sam_syslog(LOG_ERR, "Unable to start thread manage_list: %m.\n"); thr_kill(threads[SONY_MSG_THREAD], SIGINT); thr_exit(NULL); } mutex_lock(&library->un->mutex); library->un->dt.rb.process = getpid(); library->un->status.b.ready = FALSE; library->un->status.b.present = FALSE; mutex_unlock(&library->un->mutex); /* * Initialize the library. This will release the library mutex. */ memccpy(l_mess, catgets(catfd, SET, 9065, "initializing"), '\0', DIS_MES_LEN); if (initialize(library, dev_ptr_tbl)) thr_exit(NULL); /* * Now let the other threads run */ thr_yield(); mutex_lock(&library->mutex); i = 30; { char *MES_9155 = catgets(catfd, SET, 9155, "waiting for %d drives to initialize"); char *mes = (char *)malloc_wait(strlen(MES_9155) + 15, 5, 0); while (library->countdown && i-- > 0) { sprintf(mes, MES_9155, library->countdown); memccpy(l_mess, mes, '\0', DIS_MES_LEN); sam_syslog(LOG_INFO, catgets(catfd, SET, 9156, "%s: Waiting for %d drives to initialize."), ent_pnt, library->countdown); mutex_unlock(&library->mutex); sleep(10); mutex_lock(&library->mutex); } free(mes); } if (i <= 0) sam_syslog(LOG_INFO, catgets(catfd, SET, 9157, "%s: %d drive(s) did not initialize."), ent_pnt, library->countdown); mutex_unlock(&library->mutex); memccpy(l_mess, "running", '\0', DIS_MES_LEN); mutex_lock(&library->un->mutex); library->un->status.b.audit = FALSE; library->un->status.b.requested = FALSE; library->un->status.b.mounted = TRUE; library->un->status.b.ready = TRUE; mutex_unlock(&library->un->mutex); /* * Now that the daemon is fully initialized, the main thread is * just used to monitor the thread state and an indication of shutdown. * This is accomplished using the signals SIGALRM, SIGINT, and SIGTERM. * This is not done with a signal handler, but using the sigwait() call. */ sigemptyset(&sigwait_set); sigaddset(&sigwait_set, SIGINT); sigaddset(&sigwait_set, SIGTERM); sigaddset(&sigwait_set, SIGALRM); /* want to restart system calls */ sig_action.sa_handler = SIG_DFL; sigemptyset(&sig_action.sa_mask); sig_action.sa_flags = SA_RESTART; sigaction(SIGINT, &sig_action, NULL); sigaction(SIGTERM, &sig_action, NULL); sigaction(SIGALRM, &sig_action, NULL); for (;;) { alarm(20); what_signal = sigwait(&sigwait_set); switch (what_signal) { case SIGALRM: if ((threads[SONY_MSG_THREAD] == (thread_t)-1) || (threads[SONY_WORK_THREAD] == (thread_t)-1)) { /* * If any of the processing threads * have disappeared, log the * fact, and take a core dump */ sam_syslog(LOG_INFO, "%s: SIGALRM: Thread(s) gone.", ent_pnt); abort(); } break; /* * For a normal shutdown of the robot daemon: * 1) prevent the alarm from going off during * shutdown and causing a core dump * 2) log the reason we are shutting down * 3) kill the helper pid if there is one * 4) terminate the connection to the catalog * 5) terminate all of the processing threads */ case SIGINT: case SIGTERM: sigdelset(&sigwait_set, SIGALRM); sam_syslog(LOG_INFO, "%s: Shutdown by signal %d", ent_pnt, what_signal); if (library->helper_pid > 0) { kill(library->helper_pid, 9); } kill_off_threads(library); exit(0); break; default: break; } } }
void PGPThreadKill( PGPThread_t tid, int sig ) { thr_kill( tid, sig ); }
/* clean up a group */ void vntsd_clean_group(vntsd_group_t *groupp) { timestruc_t to; D1(stderr, "t@%d clean_group() group=%s tcp=%lld\n", thr_self(), groupp->group_name, groupp->tcp_port); (void) mutex_lock(&groupp->lock); /* prevent from reentry */ if (groupp->status & VNTSD_GROUP_CLEANUP) { (void) mutex_unlock(&groupp->lock); return; } groupp->status |= VNTSD_GROUP_CLEANUP; vntsd_free_que(&groupp->conspq, (clean_func_t)cleanup_cons); (void) mutex_unlock(&groupp->lock); /* walk through no cons client queue */ while (groupp->no_cons_clientpq != NULL) { groupp->status |= VNTSD_GROUP_SIG_WAIT; (void) vntsd_que_walk(groupp->no_cons_clientpq, (el_func_t)vntsd_notify_client_cons_del); to.tv_sec = VNTSD_CV_WAIT_DELTIME; to.tv_nsec = 0; (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to); } if (groupp->listen_tid == thr_self()) { /* listen thread is exiting */ (void) mutex_lock(&(groupp->vntsd->lock)); (void) vntsd_que_rm(&groupp->vntsd->grouppq, groupp); (void) mutex_unlock(&groupp->vntsd->lock); (void) cond_destroy(&groupp->cvp); (void) mutex_unlock(&groupp->lock); (void) mutex_destroy(&groupp->lock); free(groupp); return; } /* signal listen thread to exit */ groupp->status |= VNTSD_GROUP_SIG_WAIT; while (groupp->status & VNTSD_GROUP_SIG_WAIT) { (void) thr_kill(groupp->listen_tid, SIGUSR1); to.tv_sec = VNTSD_CV_WAIT_DELTIME; to.tv_nsec = 0; /* wait listen thread to exit */ (void) cond_reltimedwait(&groupp->cvp, &groupp->lock, &to); } (void) mutex_unlock(&groupp->lock); (void) thr_join(groupp->listen_tid, NULL, NULL); /* free group */ (void) cond_destroy(&groupp->cvp); (void) mutex_destroy(&groupp->lock); free(groupp); }
main() { int i; struct sigaction act; act.sa_handler = ExitHandler; (void) sigemptyset(&act.sa_mask); (void) sigaction(SIGTERM, &act, NULL); mutex_init(&first_mutex, 0 , 0); mutex_init(&second_mutex, 0 , 0); main_thread = thr_self(); thr_create(NULL,0,first_thread,0,THR_NEW_LWP,&one_tid); thr_create(NULL,0,second_thread,0,THR_NEW_LWP,&two_tid); for (i = 0; i < 10; i++){ fprintf(stderr, "main loop: %d\n", i); if (i == 5) { thr_kill(one_tid, SIGTERM); } sleep(3); } thr_kill(two_tid, SIGTERM); sleep(5); fprintf(stderr, "main exit\n"); }