Skip to content

Commit 45fbfa2

Browse files
author
rhc54
committed
Merge pull request #1748 from rhc54/topic/abrt2
Cleanup the forced termination a bit by restoring the delay before is…
2 parents ef12c13 + 0ba9572 commit 45fbfa2

File tree

4 files changed

+76
-149
lines changed

4 files changed

+76
-149
lines changed

orte/mca/odls/alps/odls_alps_module.c

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -164,70 +164,6 @@ orte_odls_base_module_t orte_odls_alps_module = {
164164
};
165165

166166

167-
static bool odls_alps_child_died(orte_proc_t *child)
168-
{
169-
time_t end;
170-
pid_t ret;
171-
172-
/* Because of rounding in time (which returns whole seconds) we
173-
* have to add 1 to our wait number: this means that we wait
174-
* somewhere between (target) and (target)+1 seconds. Otherwise,
175-
* the default 1s actually means 'somwhere between 0 and 1s'. */
176-
end = time(NULL) + orte_odls_globals.timeout_before_sigkill + 1;
177-
do {
178-
OPAL_OUTPUT_VERBOSE((20, orte_odls_base_framework.framework_output,
179-
"%s odls:alps:WAITPID CHECKING PID %d WITH TIMEOUT %d SECONDS",
180-
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), (int)(child->pid),
181-
orte_odls_globals.timeout_before_sigkill + 1));
182-
ret = waitpid(child->pid, &child->exit_code, WNOHANG);
183-
if (child->pid == ret) {
184-
OPAL_OUTPUT_VERBOSE((20, orte_odls_base_framework.framework_output,
185-
"%s odls:alps:WAITPID INDICATES PROC %d IS DEAD",
186-
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), (int)(child->pid)));
187-
/* It died -- return success */
188-
return true;
189-
} else if (0 == ret) {
190-
/* with NOHANG specified, if a process has already exited
191-
* while waitpid was registered, then waitpid returns 0
192-
* as there is no error - this is a race condition problem
193-
* that occasionally causes us to incorrectly report a proc
194-
* as refusing to die. Unfortunately, errno may not be reset
195-
* by waitpid in this case, so we cannot check it.
196-
*
197-
* (note the previous fix to this, to return 'process dead'
198-
* here, fixes the race condition at the cost of reporting
199-
* all live processes have immediately died! Better to
200-
* occasionally report a dead process as still living -
201-
* which will occasionally trip the timeout for cases that
202-
* are right on the edge.)
203-
*/
204-
OPAL_OUTPUT_VERBOSE((20, orte_odls_base_framework.framework_output,
205-
"%s odls:alps:WAITPID INDICATES PID %d MAY HAVE ALREADY EXITED",
206-
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), (int)(child->pid)));
207-
/* Do nothing, process still alive */
208-
} else if (-1 == ret && ECHILD == errno) {
209-
/* The pid no longer exists, so we'll call this "good
210-
enough for government work" */
211-
OPAL_OUTPUT_VERBOSE((20, orte_odls_base_framework.framework_output,
212-
"%s odls:alps:WAITPID INDICATES PID %d NO LONGER EXISTS",
213-
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), (int)(child->pid)));
214-
return true;
215-
}
216-
217-
/* Bogus delay for 1 msec - let's actually give the CPU some time
218-
* to quit the other process (sched_yield() -- even if we have it
219-
* -- changed behavior in 2.6.3x Linux flavors to be undesirable)
220-
* Don't use select on a bogus file descriptor here as it has proven
221-
* unreliable and sometimes immediately returns - we really, really
222-
* -do- want to wait a bit!
223-
*/
224-
usleep(1000);
225-
} while (time(NULL) < end);
226-
227-
/* The child didn't die, so return false */
228-
return false;
229-
}
230-
231167
static int odls_alps_kill_local(pid_t pid, int signum)
232168
{
233169
pid_t pgrp;
@@ -264,7 +200,7 @@ int orte_odls_alps_kill_local_procs(opal_pointer_array_t *procs)
264200
int rc;
265201

266202
if (ORTE_SUCCESS != (rc = orte_odls_base_default_kill_local_procs(procs,
267-
odls_alps_kill_local, odls_alps_child_died))) {
203+
odls_alps_kill_local))) {
268204
ORTE_ERROR_LOG(rc);
269205
return rc;
270206
}

orte/mca/odls/base/odls_base_default_fns.c

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,16 +1366,65 @@ void odls_base_default_wait_local_proc(orte_proc_t *proc, void* cbdata)
13661366
ORTE_ACTIVATE_PROC_STATE(&proc->name, state);
13671367
}
13681368

1369+
typedef struct {
1370+
opal_object_t super;
1371+
orte_proc_t *child;
1372+
orte_odls_base_kill_local_fn_t kill_local;
1373+
} orte_odls_quick_caddy_t;
1374+
static void qcdcon(orte_odls_quick_caddy_t *p)
1375+
{
1376+
p->child = NULL;
1377+
p->kill_local = NULL;
1378+
}
1379+
static void qcddes(orte_odls_quick_caddy_t *p)
1380+
{
1381+
if (NULL != p->child) {
1382+
OBJ_RELEASE(p->child);
1383+
}
1384+
}
1385+
OBJ_CLASS_INSTANCE(orte_odls_quick_caddy_t,
1386+
opal_object_t,
1387+
qcdcon, qcddes);
1388+
1389+
static void send_kill(int sd, short args, void *cbdata)
1390+
{
1391+
orte_timer_t *tm = (orte_timer_t*)cbdata;
1392+
orte_odls_quick_caddy_t *cd = (orte_odls_quick_caddy_t*)tm->payload;
1393+
1394+
OPAL_OUTPUT_VERBOSE((5, orte_odls_base_framework.framework_output,
1395+
"%s SENDING FORCE SIGKILL TO %s",
1396+
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
1397+
ORTE_NAME_PRINT(&cd->child->name)));
1398+
1399+
cd->kill_local(cd->child->pid, SIGKILL);
1400+
/* indicate the waitpid fired as this is effectively what
1401+
* has happened
1402+
*/
1403+
ORTE_FLAG_SET(cd->child, ORTE_PROC_FLAG_WAITPID);
1404+
cd->child->pid = 0;
1405+
1406+
/* ensure the child's session directory is cleaned up */
1407+
orte_session_dir_finalize(&cd->child->name);
1408+
/* check for everything complete - this will remove
1409+
* the child object from our local list
1410+
*/
1411+
if (ORTE_FLAG_TEST(cd->child, ORTE_PROC_FLAG_IOF_COMPLETE) &&
1412+
ORTE_FLAG_TEST(cd->child, ORTE_PROC_FLAG_WAITPID)) {
1413+
ORTE_ACTIVATE_PROC_STATE(&cd->child->name, cd->child->state);
1414+
}
1415+
OBJ_RELEASE(cd);
1416+
}
1417+
13691418
int orte_odls_base_default_kill_local_procs(opal_pointer_array_t *procs,
1370-
orte_odls_base_kill_local_fn_t kill_local,
1371-
orte_odls_base_child_died_fn_t child_died)
1419+
orte_odls_base_kill_local_fn_t kill_local)
13721420
{
13731421
orte_proc_t *child;
13741422
opal_list_t procs_killed;
13751423
orte_proc_t *proc, proctmp;
13761424
int i, j;
13771425
opal_pointer_array_t procarray, *procptr;
13781426
bool do_cleanup;
1427+
orte_odls_quick_caddy_t *cd;
13791428

13801429
OBJ_CONSTRUCT(&procs_killed, opal_list_t);
13811430

@@ -1492,22 +1541,30 @@ int orte_odls_base_default_kill_local_procs(opal_pointer_array_t *procs,
14921541
*/
14931542
orte_wait_cb_cancel(child);
14941543

1495-
/* Use SIGKILL just to make sure things are dead
1496-
* This fixes an issue that, if the application is masking
1497-
* SIGTERM, then the child_died() may return 'true' even
1498-
* though waipid returns with 0. It does this to avoid a
1499-
* race condition, per documentation in odls_default_module.c.
1500-
*/
1544+
/* First send a SIGCONT in case the process is in stopped state.
1545+
If it is in a stopped state and we do not first change it to
1546+
running, then SIGTERM will not get delivered. Ignore return
1547+
value. */
15011548
OPAL_OUTPUT_VERBOSE((5, orte_odls_base_framework.framework_output,
1502-
"%s SENDING FORCE SIGKILL TO %s pid %lu",
1549+
"%s SENDING SIGCONT TO %s",
15031550
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
1504-
ORTE_NAME_PRINT(&child->name), (unsigned long)child->pid));
1505-
kill_local(child->pid, SIGKILL);
1506-
/* indicate the waitpid fired as this is effectively what
1507-
* has happened
1508-
*/
1509-
ORTE_FLAG_SET(child, ORTE_PROC_FLAG_WAITPID);
1510-
child->pid = 0;
1551+
ORTE_NAME_PRINT(&child->name)));
1552+
kill_local(child->pid, SIGCONT);
1553+
1554+
/* Send a sigterm to the process before sigkill to be nice */
1555+
OPAL_OUTPUT_VERBOSE((5, orte_odls_base_framework.framework_output,
1556+
"%s SENDING SIGTERM TO %s",
1557+
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME),
1558+
ORTE_NAME_PRINT(&child->name)));
1559+
kill_local(child->pid, SIGTERM);
1560+
1561+
cd = OBJ_NEW(orte_odls_quick_caddy_t);
1562+
OBJ_RETAIN(child);
1563+
cd->child = child;
1564+
cd->kill_local = kill_local;
1565+
ORTE_DETECT_TIMEOUT(1, orte_odls_globals.timeout_before_sigkill,
1566+
10000000, send_kill, cd);
1567+
continue;
15111568

15121569
CLEANUP:
15131570
/* ensure the child's session directory is cleaned up */

orte/mca/odls/base/odls_private.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,7 @@ typedef bool (*orte_odls_base_child_died_fn_t)(orte_proc_t *child);
121121

122122
ORTE_DECLSPEC int
123123
orte_odls_base_default_kill_local_procs(opal_pointer_array_t *procs,
124-
orte_odls_base_kill_local_fn_t kill_local,
125-
orte_odls_base_child_died_fn_t child_died);
124+
orte_odls_base_kill_local_fn_t kill_local);
126125

127126
ORTE_DECLSPEC int orte_odls_base_default_restart_proc(orte_proc_t *child,
128127
orte_odls_base_fork_local_proc_fn_t fork_local);

orte/mca/odls/default/odls_default_module.c

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -164,71 +164,6 @@ orte_odls_base_module_t orte_odls_default_module = {
164164
};
165165

166166

167-
static bool odls_default_child_died(orte_proc_t *child)
168-
{
169-
time_t end;
170-
pid_t ret;
171-
172-
/* Because of rounding in time (which returns whole seconds) we
173-
* have to add 1 to our wait number: this means that we wait
174-
* somewhere between (target) and (target)+1 seconds. Otherwise,
175-
* the default 1s actually means 'somwhere between 0 and 1s'. */
176-
end = time(NULL) + orte_odls_globals.timeout_before_sigkill + 1;
177-
do {
178-
OPAL_OUTPUT_VERBOSE((20, orte_odls_base_framework.framework_output,
179-
"%s odls:default:WAITPID CHECKING PID %d WITH TIMEOUT %d SECONDS",
180-
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), (int)(child->pid),
181-
orte_odls_globals.timeout_before_sigkill + 1));
182-
ret = waitpid(child->pid, &child->exit_code, WNOHANG);
183-
if (child->pid == ret) {
184-
OPAL_OUTPUT_VERBOSE((20, orte_odls_base_framework.framework_output,
185-
"%s odls:default:WAITPID INDICATES PROC %d IS DEAD",
186-
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), (int)(child->pid)));
187-
/* It died -- return success */
188-
return true;
189-
} else if (0 == ret) {
190-
/* with NOHANG specified, if a process has already exited
191-
* while waitpid was registered, then waitpid returns 0
192-
* as there is no error - this is a race condition problem
193-
* that occasionally causes us to incorrectly report a proc
194-
* as refusing to die. Unfortunately, errno may not be reset
195-
* by waitpid in this case, so we cannot check it.
196-
*
197-
* (note the previous fix to this, to return 'process dead'
198-
* here, fixes the race condition at the cost of reporting
199-
* all live processes have immediately died! Better to
200-
* occasionally report a dead process as still living -
201-
* which will occasionally trip the timeout for cases that
202-
* are right on the edge.)
203-
*/
204-
OPAL_OUTPUT_VERBOSE((20, orte_odls_base_framework.framework_output,
205-
"%s odls:default:WAITPID INDICATES PID %d MAY HAVE ALREADY EXITED",
206-
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), (int)(child->pid)));
207-
/* Do nothing, process still alive */
208-
} else if (-1 == ret && ECHILD == errno) {
209-
/* The pid no longer exists, so we'll call this "good
210-
enough for government work" */
211-
OPAL_OUTPUT_VERBOSE((20, orte_odls_base_framework.framework_output,
212-
"%s odls:default:WAITPID INDICATES PID %d NO LONGER EXISTS",
213-
ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), (int)(child->pid)));
214-
return true;
215-
}
216-
217-
/* Bogus delay for 1 msec - let's actually give the CPU some time
218-
* to quit the other process (sched_yield() -- even if we have it
219-
* -- changed behavior in 2.6.3x Linux flavors to be undesirable)
220-
* Don't use select on a bogus file descriptor here as it has proven
221-
* unreliable and sometimes immediately returns - we really, really
222-
* -do- want to wait a bit!
223-
*/
224-
usleep(1000);
225-
} while (time(NULL) < end);
226-
227-
/* The child didn't die, so return false */
228-
return false;
229-
}
230-
231-
232167
/* deliver a signal to a specified pid. */
233168
static int odls_default_kill_local(pid_t pid, int signum)
234169
{
@@ -251,7 +186,7 @@ int orte_odls_default_kill_local_procs(opal_pointer_array_t *procs)
251186
int rc;
252187

253188
if (ORTE_SUCCESS != (rc = orte_odls_base_default_kill_local_procs(procs,
254-
odls_default_kill_local, odls_default_child_died))) {
189+
odls_default_kill_local))) {
255190
ORTE_ERROR_LOG(rc);
256191
return rc;
257192
}

0 commit comments

Comments
 (0)