summaryrefslogtreecommitdiff
path: root/src/basic/process-util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/basic/process-util.c')
-rw-r--r--src/basic/process-util.c72
1 files changed, 61 insertions, 11 deletions
diff --git a/src/basic/process-util.c b/src/basic/process-util.c
index 611fd2339..2494ba6af 100644
--- a/src/basic/process-util.c
+++ b/src/basic/process-util.c
@@ -26,7 +26,6 @@
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
-#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
@@ -131,8 +130,6 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
return -errno;
}
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
-
if (max_length == 1) {
/* If there's only room for one byte, return the empty string */
@@ -411,8 +408,6 @@ int is_kernel_thread(pid_t pid) {
return -errno;
}
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
-
count = fread(&c, 1, 1, f);
eof = feof(f);
fclose(f);
@@ -497,8 +492,6 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
return -errno;
}
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
-
FOREACH_LINE(line, f, return -errno) {
char *l;
@@ -577,8 +570,6 @@ int get_process_environ(pid_t pid, char **env) {
return -errno;
}
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
-
while ((c = fgetc(f)) != EOF) {
if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
return -ENOMEM;
@@ -714,6 +705,67 @@ int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_cod
return -EPROTO;
}
+/*
+ * Return values:
+ * < 0 : wait_for_terminate_with_timeout() failed to get the state of the
+ * process, the process timed out, the process was terminated by a
+ * signal, or failed for an unknown reason.
+ * >=0 : The process terminated normally with no failures.
+ *
+ * Success is indicated by a return value of zero, a timeout is indicated
+ * by ETIMEDOUT, and all other child failure states are indicated by error
+ * is indicated by a non-zero value.
+ */
+int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) {
+ sigset_t mask;
+ int r;
+ usec_t until;
+
+ assert_se(sigemptyset(&mask) == 0);
+ assert_se(sigaddset(&mask, SIGCHLD) == 0);
+
+ /* Drop into a sigtimewait-based timeout. Waiting for the
+ * pid to exit. */
+ until = now(CLOCK_MONOTONIC) + timeout;
+ for (;;) {
+ usec_t n;
+ siginfo_t status = {};
+ struct timespec ts;
+
+ n = now(CLOCK_MONOTONIC);
+ if (n >= until)
+ break;
+
+ r = sigtimedwait(&mask, NULL, timespec_store(&ts, until - n)) < 0 ? -errno : 0;
+ /* Assuming we woke due to the child exiting. */
+ if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) {
+ if (status.si_pid == pid) {
+ /* This is the correct child.*/
+ if (status.si_code == CLD_EXITED)
+ return (status.si_status == 0) ? 0 : -EPROTO;
+ else
+ return -EPROTO;
+ }
+ }
+ /* Not the child, check for errors and proceed appropriately */
+ if (r < 0) {
+ switch (r) {
+ case -EAGAIN:
+ /* Timed out, child is likely hung. */
+ return -ETIMEDOUT;
+ case -EINTR:
+ /* Received a different signal and should retry */
+ continue;
+ default:
+ /* Return any unexpected errors */
+ return r;
+ }
+ }
+ }
+
+ return -EPROTO;
+}
+
#if 0 /// UNNEEDED by elogind
void sigkill_wait(pid_t pid) {
assert(pid > 1);
@@ -766,8 +818,6 @@ int getenv_for_pid(pid_t pid, const char *field, char **_value) {
return -errno;
}
- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
-
l = strlen(field);
r = 0;