core: add @max_wait_msec argument to nm_utils_kill_process_sync()
This commit is contained in:
@@ -870,20 +870,25 @@ out:
|
|||||||
* @log_name: name of the process to kill for logging.
|
* @log_name: name of the process to kill for logging.
|
||||||
* @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
|
* @wait_before_kill_msec: Waittime in milliseconds before sending %SIGKILL signal. Set this value
|
||||||
* to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter has no effect.
|
* to zero, not to send %SIGKILL. If @sig is already %SIGKILL, this parameter has no effect.
|
||||||
|
* If @max_wait_msec is set but less then @wait_before_kill_msec, the final %SIGKILL will also
|
||||||
|
* not be send.
|
||||||
* @sleep_duration_msec: the synchronous function sleeps repeatedly waiting for the child to terminate.
|
* @sleep_duration_msec: the synchronous function sleeps repeatedly waiting for the child to terminate.
|
||||||
* Set to zero, to use the default (meaning 20 wakeups per seconds).
|
* Set to zero, to use the default (meaning 20 wakeups per seconds).
|
||||||
|
* @max_wait_msec: if 0, waits indefinitely until the process is gone (or a zombie). Otherwise, this
|
||||||
|
* is the maxium wait time until returning. If @max_wait_msec is non-zero but smaller then @wait_before_kill_msec,
|
||||||
|
* we will not send a final %SIGKILL.
|
||||||
*
|
*
|
||||||
* Kill a non-child process synchronously and wait. This function will not return before the
|
* Kill a non-child process synchronously and wait. This function will not return before the
|
||||||
* process with PID @pid is gone or the process is a zombie.
|
* process with PID @pid is gone, the process is a zombie, or @max_wait_msec expires.
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, NMLogDomain log_domain,
|
nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, NMLogDomain log_domain,
|
||||||
const char *log_name, guint32 wait_before_kill_msec,
|
const char *log_name, guint32 wait_before_kill_msec,
|
||||||
guint32 sleep_duration_msec)
|
guint32 sleep_duration_msec, guint32 max_wait_msec)
|
||||||
{
|
{
|
||||||
int errsv;
|
int errsv;
|
||||||
guint64 start_time0;
|
guint64 start_time0;
|
||||||
gint64 wait_until, now, wait_start_us;
|
gint64 wait_until_sigkill, now, wait_start_us, max_wait_until;
|
||||||
gulong sleep_time, sleep_duration_usec;
|
gulong sleep_time, sleep_duration_usec;
|
||||||
int loop_count = 0;
|
int loop_count = 0;
|
||||||
gboolean was_waiting = FALSE;
|
gboolean was_waiting = FALSE;
|
||||||
@@ -935,7 +940,16 @@ nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, NMLogDomain
|
|||||||
wait_start_us = nm_utils_get_monotonic_timestamp_us ();
|
wait_start_us = nm_utils_get_monotonic_timestamp_us ();
|
||||||
|
|
||||||
sleep_duration_usec = _sleep_duration_convert_ms_to_us (sleep_duration_msec);
|
sleep_duration_usec = _sleep_duration_convert_ms_to_us (sleep_duration_msec);
|
||||||
wait_until = wait_start_us + (((gint64) wait_before_kill_msec) * 1000L);
|
if (sig != SIGKILL)
|
||||||
|
wait_until_sigkill = wait_start_us + (((gint64) wait_before_kill_msec) * 1000L);
|
||||||
|
else
|
||||||
|
wait_until_sigkill = 0;
|
||||||
|
if (max_wait_msec > 0) {
|
||||||
|
max_wait_until = wait_start_us + (((gint64) max_wait_msec) * 1000L);
|
||||||
|
if (wait_until_sigkill > 0 && wait_until_sigkill > max_wait_msec)
|
||||||
|
wait_until_sigkill = 0;
|
||||||
|
} else
|
||||||
|
max_wait_until = 0;
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
start_time = nm_utils_get_start_time_for_pid (pid, &p_state);
|
start_time = nm_utils_get_start_time_for_pid (pid, &p_state);
|
||||||
@@ -974,9 +988,25 @@ nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, NMLogDomain
|
|||||||
}
|
}
|
||||||
|
|
||||||
sleep_time = sleep_duration_usec;
|
sleep_time = sleep_duration_usec;
|
||||||
if (wait_until != 0) {
|
|
||||||
now = nm_utils_get_monotonic_timestamp_us ();
|
now = nm_utils_get_monotonic_timestamp_us ();
|
||||||
if (sig != SIGKILL && now >= wait_until) {
|
|
||||||
|
if ( max_wait_until != 0
|
||||||
|
&& now >= max_wait_until) {
|
||||||
|
if (wait_until_sigkill != 0) {
|
||||||
|
/* wait_before_kill_msec is not larger then max_wait_until but we did not yet send
|
||||||
|
* SIGKILL. Although we already reached our timeout, we don't want to skip sending
|
||||||
|
* the signal. Even if we don't wait for the process to disappear. */
|
||||||
|
nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": sending SIGKILL", LOG_NAME_ARGS);
|
||||||
|
kill (pid, SIGKILL);
|
||||||
|
}
|
||||||
|
nm_log_warn (log_domain, LOG_NAME_PROCESS_FMT ": timeout %u msec waiting for process to disappear (after sending %s)%s",
|
||||||
|
LOG_NAME_ARGS, (unsigned) max_wait_until, _kc_signal_to_string (sig),
|
||||||
|
was_waiting ? _kc_waited_to_string (buf_wait, wait_start_us) : "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait_until_sigkill != 0) {
|
||||||
|
if (now >= wait_until_sigkill) {
|
||||||
/* Still not dead. SIGKILL now... */
|
/* Still not dead. SIGKILL now... */
|
||||||
nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": sending SIGKILL", LOG_NAME_ARGS);
|
nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": sending SIGKILL", LOG_NAME_ARGS);
|
||||||
if (kill (pid, SIGKILL) != 0) {
|
if (kill (pid, SIGKILL) != 0) {
|
||||||
@@ -993,18 +1023,25 @@ nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, NMLogDomain
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sig = SIGKILL;
|
sig = SIGKILL;
|
||||||
was_waiting = TRUE;
|
wait_until_sigkill = 0;
|
||||||
wait_until = 0;
|
|
||||||
loop_count = 0; /* reset the loop_count. Now we really expect the process to die quickly. */
|
loop_count = 0; /* reset the loop_count. Now we really expect the process to die quickly. */
|
||||||
} else {
|
} else
|
||||||
|
sleep_time = MIN (wait_until_sigkill - now, sleep_duration_usec);
|
||||||
|
}
|
||||||
|
|
||||||
if (!was_waiting) {
|
if (!was_waiting) {
|
||||||
nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting up to %ld milliseconds for process to disappear after sending %s...",
|
if (wait_until_sigkill != 0) {
|
||||||
|
nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting up to %ld milliseconds for process to disappear before sending KILL signal after sending %s...",
|
||||||
LOG_NAME_ARGS, (long) wait_before_kill_msec, _kc_signal_to_string (sig));
|
LOG_NAME_ARGS, (long) wait_before_kill_msec, _kc_signal_to_string (sig));
|
||||||
|
} else if (max_wait_until != 0) {
|
||||||
|
nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting up to %ld milliseconds for process to disappear after sending %s...",
|
||||||
|
LOG_NAME_ARGS, (long) max_wait_msec, _kc_signal_to_string (sig));
|
||||||
|
} else {
|
||||||
|
nm_log_dbg (log_domain, LOG_NAME_PROCESS_FMT ": waiting for process to disappear after sending %s...",
|
||||||
|
LOG_NAME_ARGS, _kc_signal_to_string (sig));
|
||||||
|
}
|
||||||
was_waiting = TRUE;
|
was_waiting = TRUE;
|
||||||
}
|
}
|
||||||
sleep_time = MIN (wait_until - now, sleep_duration_usec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loop_count < 20) {
|
if (loop_count < 20) {
|
||||||
/* At the beginning we expect the process to die fast.
|
/* At the beginning we expect the process to die fast.
|
||||||
|
@@ -73,7 +73,7 @@ guint64 nm_utils_get_start_time_for_pid (pid_t pid, char *out_state);
|
|||||||
|
|
||||||
void nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, guint64 log_domain,
|
void nm_utils_kill_process_sync (pid_t pid, guint64 start_time, int sig, guint64 log_domain,
|
||||||
const char *log_name, guint32 wait_before_kill_msec,
|
const char *log_name, guint32 wait_before_kill_msec,
|
||||||
guint32 sleep_duration_msec);
|
guint32 sleep_duration_msec, guint32 max_wait_msec);
|
||||||
|
|
||||||
typedef void (*NMUtilsKillChildAsyncCb) (pid_t pid, gboolean success, int child_status, void *user_data);
|
typedef void (*NMUtilsKillChildAsyncCb) (pid_t pid, gboolean success, int child_status, void *user_data);
|
||||||
void nm_utils_kill_child_async (pid_t pid, int sig, guint64 log_domain, const char *log_name,
|
void nm_utils_kill_child_async (pid_t pid, int sig, guint64 log_domain, const char *log_name,
|
||||||
|
@@ -604,7 +604,7 @@ nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name)
|
|||||||
|
|
||||||
if (!strcmp (exe, binary_name))
|
if (!strcmp (exe, binary_name))
|
||||||
nm_utils_kill_process_sync (tmp, start_time, SIGTERM, LOGD_DHCP,
|
nm_utils_kill_process_sync (tmp, start_time, SIGTERM, LOGD_DHCP,
|
||||||
"dhcp-client", 1000 / 2, 1000 / 20);
|
"dhcp-client", 1000 / 2, 1000 / 20, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user