static apr_status_t piped_log_cleanup(void *data) { piped_log *pl = data; if (pl->pid != NULL) { apr_proc_kill(pl->pid, SIGTERM); } return piped_log_cleanup_for_exec(data); }
static void piped_log_maintenance(int reason, void *data, apr_wait_t status) { piped_log *pl = data; apr_status_t stats; int mpm_state; switch (reason) { case APR_OC_REASON_DEATH: case APR_OC_REASON_LOST: pl->pid = NULL; /* in case we don't get it going again, this * tells other logic not to try to kill it */ apr_proc_other_child_unregister(pl); stats = ap_mpm_query(AP_MPMQ_MPM_STATE, &mpm_state); if (stats != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "can't query MPM state; not restarting " "piped log program '%s'", pl->program); } else if (mpm_state != AP_MPMQ_STOPPING) { ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "piped log program '%s' failed unexpectedly", pl->program); if ((stats = piped_log_spawn(pl)) != APR_SUCCESS) { /* what can we do? This could be the error log we're having * problems opening up... */ char buf[120]; ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "piped_log_maintenance: unable to respawn '%s': %s", pl->program, apr_strerror(stats, buf, sizeof(buf))); } } break; case APR_OC_REASON_UNWRITABLE: /* We should not kill off the pipe here, since it may only be full. * If it really is locked, we should kill it off manually. */ break; case APR_OC_REASON_RESTART: if (pl->pid != NULL) { apr_proc_kill(pl->pid, SIGTERM); pl->pid = NULL; } break; case APR_OC_REASON_UNREGISTER: break; } }
static int proc_kill(lua_State *L) { const char *options[] = { "never", "always", "timeout", "wait", "once", NULL, }; const apr_kill_conditions_e values[] = { APR_KILL_NEVER, APR_KILL_ALWAYS, APR_KILL_AFTER_TIMEOUT, APR_JUST_WAIT, APR_KILL_ONLY_ONCE, }; apr_status_t status; lua_apr_proc *process; int option; process = proc_check(L, 1); option = values[luaL_checkoption(L, 2, NULL, options)]; status = apr_proc_kill(&process->handle, option); return push_status(L, status); }
/* It would be great if we could stress this stuff more, and make the test * more granular. */ static void test_child_kill(abts_case *tc, void *data) { apr_file_t *std = NULL; apr_proc_t newproc; apr_procattr_t *procattr = NULL; const char *args[3]; apr_status_t rv; args[0] = apr_pstrdup(p, "occhild" EXTENSION); args[1] = apr_pstrdup(p, "-X"); args[2] = NULL; rv = apr_procattr_create(&procattr, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_NO_PIPE, APR_NO_PIPE); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_proc_create(&newproc, "./occhild" EXTENSION, args, NULL, procattr, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_PTR_NOTNULL(tc, newproc.in); ABTS_PTR_EQUAL(tc, NULL, newproc.out); ABTS_PTR_EQUAL(tc, NULL, newproc.err); std = newproc.in; apr_proc_other_child_register(&newproc, ocmaint, NULL, std, p); apr_sleep(apr_time_from_sec(1)); rv = apr_proc_kill(&newproc, SIGKILL); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); /* allow time for things to settle... */ apr_sleep(apr_time_from_sec(3)); apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING); ABTS_STR_EQUAL(tc, "APR_OC_REASON_DEATH", reasonstr); }
apr_status_t proc_kill_force(fcgid_procnode *procnode, server_rec *main_server) { return apr_proc_kill(&(procnode->proc_id), SIGKILL); }
static void im_exec_stop(nx_module_t *module) { nx_im_exec_conf_t *imconf; int i; boolean sigterm_sent = FALSE; apr_exit_why_e exitwhy; int exitval; int sig_num; apr_status_t rv; apr_status_t stopped = APR_SUCCESS; ASSERT(module != NULL); imconf = (nx_im_exec_conf_t *) module->config; ASSERT(imconf != NULL); log_debug("im_exec stopped"); if ( module->input.desc.f != NULL ) { apr_file_close(module->input.desc.f); apr_pool_clear(module->input.pool); module->input.desc.f = NULL; } if ( imconf->running == TRUE ) { for ( i = 0; i < 50; i++ ) { if ( (rv = apr_proc_wait(&(imconf->proc), &exitval, &exitwhy, APR_NOWAIT)) != APR_SUCCESS ) { if ( APR_STATUS_IS_CHILD_DONE(rv) ) { rv = APR_SUCCESS; break; } else if ( i >= 30 ) { // still running, kill it after 3 sec if ( sigterm_sent == FALSE ) { sigterm_sent = TRUE; #ifdef WIN32 sig_num = 1; #else sig_num = SIGTERM; #endif } else { if ( i <= 31 ) { log_warn("process %s did not exit, killing it.", imconf->cmd); } #ifdef WIN32 sig_num = 1; #else sig_num = SIGKILL; #endif } if ( (rv = apr_proc_kill(&(imconf->proc), sig_num)) != APR_SUCCESS ) { stopped = rv; } } } apr_sleep(APR_USEC_PER_SEC / 10); } if ( !((stopped == APR_SUCCESS) || APR_STATUS_IS_ENOPROC(stopped)) ) { log_aprerror(stopped, "im_exec couldn't stop process"); } } imconf->event = NULL; }
/** Kill a process with a given pid. * * Used to from the apache module thread to kill the trell master job, and * we try to wait and determine if the process is dead. */ static int trell_kill_process( trell_sconf_t* svr_conf, request_rec* r, pid_t pid ) { int i; apr_status_t rv; // Shaky..? apr_proc_t proc; proc.pid = pid; proc.in = NULL; proc.out = NULL; proc.err = NULL; // This is slightly shaky as well, since we're not necessarily the parent // process, and if the child isn't waited upon, we have a defunct/zombie. rv = apr_proc_kill( &proc, SIGTERM ); if( rv != APR_SUCCESS ) { ap_log_rerror( APLOG_MARK, APLOG_NOTICE, rv, r, "mod_trell: %s@%d", __FILE__, __LINE__ ); return rv; } ap_log_rerror( APLOG_MARK, APLOG_NOTICE, OK, r, "mod_trell: Sent pid=%d SIGTERM", proc.pid ); apr_sleep( 1000 ); // Slight wait to let process hopefully terminate. for(i=0; i<3; i++ ) { // Check if child is dead. However, it is not safe to assume that the // master is child of current process. int exitcode; apr_exit_why_e why=0; rv = apr_proc_wait( &proc, &exitcode, &why, APR_NOWAIT ); if( rv == APR_CHILD_DONE ) { ap_log_rerror( APLOG_MARK, APLOG_NOTICE, OK, r, "mod_trell: SIGTERM why=%d", why ); return APR_SUCCESS; } // Wait failed, check to see if the messenger still lives... If not, // we assume it's dead. struct messenger msgr; messenger_status_t status = messenger_init( &msgr, svr_conf->m_master_id ); if( status != MESSENGER_OK ) { ap_log_rerror( APLOG_MARK, APLOG_NOTICE, OK, r, "mod_trell: failed to get master messenger, assuming master is dead." ); return APR_SUCCESS; } messenger_free( &msgr ); ap_log_rerror( APLOG_MARK, APLOG_NOTICE, OK, r, "mod_trell: Child not done, sleeping it=%d", i ); apr_sleep( 1000000 ); } rv = apr_proc_kill( &proc, SIGKILL ); apr_sleep( 1000 ); // Slight wait to let process hopefully terminate. if( rv != APR_SUCCESS ) { ap_log_rerror( APLOG_MARK, APLOG_NOTICE, rv, r, "mod_trell: %s@%d", __FILE__, __LINE__ ); return rv; } ap_log_rerror( APLOG_MARK, APLOG_NOTICE, OK, r, "mod_trell: Sent pid=%d SIGKILL", proc.pid ); for(i=0; i<3; i++ ) { int exitcode; apr_exit_why_e why=0; rv = apr_proc_wait( &proc, &exitcode, &why, APR_NOWAIT ); if( rv == APR_CHILD_DONE ) { ap_log_rerror( APLOG_MARK, APLOG_NOTICE, OK, r, "mod_trell: SIGKILL why=%d", why ); return APR_SUCCESS; } struct messenger msgr; messenger_status_t status = messenger_init( &msgr, svr_conf->m_master_id ); if( status != MESSENGER_OK ) { ap_log_rerror( APLOG_MARK, APLOG_NOTICE, OK, r, "mod_trell: failed to get master messenger, assuming master is dead." ); return APR_SUCCESS; } messenger_free( &msgr ); ap_log_rerror( APLOG_MARK, APLOG_NOTICE, OK, r, "mod_trell: Child not done, sleeping it=%d", i ); apr_sleep( 1000000 ); } ap_log_rerror( APLOG_MARK, APLOG_CRIT, OK, r, "mod_trell: Failed to kill master job." ); }