Merge pull request #7767 from poettering/fork-wait

A variety of smaller improvements all over the place
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2018-01-04 15:25:07 +01:00
committed by GitHub
56 changed files with 556 additions and 414 deletions
+31 -11
View File
@@ -32,32 +32,52 @@
#include "util.h"
int asynchronous_job(void* (*func)(void *p), void *arg) {
sigset_t ss, saved_ss;
pthread_attr_t a;
pthread_t t;
int r;
int r, k;
/* It kinda sucks that we have to resort to threads to
* implement an asynchronous sync(), but well, such is
* life.
*
* Note that issuing this command right before exiting a
* process will cause the process to wait for the sync() to
* complete. This function hence is nicely asynchronous really
* only in long running processes. */
/* It kinda sucks that we have to resort to threads to implement an asynchronous close(), but well, such is
* life. */
r = pthread_attr_init(&a);
if (r > 0)
return -r;
r = pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
if (r > 0)
if (r > 0) {
r = -r;
goto finish;
}
if (sigfillset(&ss) < 0) {
r = -errno;
goto finish;
}
/* Block all signals before forking off the thread, so that the new thread is started with all signals
* blocked. This way the existence of the new thread won't affect signal handling in other threads. */
r = pthread_sigmask(SIG_BLOCK, &ss, &saved_ss);
if (r > 0) {
r = -r;
goto finish;
}
r = pthread_create(&t, &a, func, arg);
k = pthread_sigmask(SIG_SETMASK, &saved_ss, NULL);
if (r > 0)
r = -r;
else if (k > 0)
r = -k;
else
r = 0;
finish:
pthread_attr_destroy(&a);
return -r;
return r;
}
int asynchronous_sync(pid_t *ret_pid) {
+7 -9
View File
@@ -156,6 +156,11 @@ static void fix_year(CalendarComponent *c) {
int calendar_spec_normalize(CalendarSpec *c) {
assert(c);
if (streq_ptr(c->timezone, "UTC")) {
c->utc = true;
c->timezone = mfree(c->timezone);
}
if (c->weekdays_bits <= 0 || c->weekdays_bits >= BITS_WEEKDAYS)
c->weekdays_bits = -1;
@@ -1349,7 +1354,6 @@ typedef struct SpecNextResult {
int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next) {
SpecNextResult *shared, tmp;
pid_t pid;
int r;
if (isempty(spec->timezone))
@@ -1359,7 +1363,7 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
if (shared == MAP_FAILED)
return negative_errno();
r = safe_fork("(sd-calendar)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG, &pid);
r = safe_fork("(sd-calendar)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT, NULL);
if (r < 0) {
(void) munmap(shared, sizeof *shared);
return r;
@@ -1377,14 +1381,8 @@ int calendar_spec_next_usec(const CalendarSpec *spec, usec_t usec, usec_t *next)
_exit(EXIT_SUCCESS);
}
r = wait_for_terminate(pid, NULL);
if (r < 0) {
(void) munmap(shared, sizeof *shared);
return r;
}
tmp = *shared;
if (munmap(shared, sizeof *shared) != 0)
if (munmap(shared, sizeof *shared) < 0)
return negative_errno();
if (tmp.return_value == 0)
+7 -18
View File
@@ -55,9 +55,9 @@ static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) {
return 0;
}
r = safe_fork("(direxec)", FORK_DEATHSIG, &_pid);
r = safe_fork("(direxec)", FORK_DEATHSIG|FORK_LOG, &_pid);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
char *_argv[2];
@@ -82,7 +82,6 @@ static int do_spawn(const char *path, char *argv[], int stdout_fd, pid_t *pid) {
_exit(EXIT_FAILURE);
}
log_debug("Spawned %s as " PID_FMT ".", path, _pid);
*pid = _pid;
return 1;
}
@@ -147,7 +146,7 @@ static int do_execute(
return log_oom();
t = NULL;
} else {
r = wait_for_terminate_and_warn(t, pid, true);
r = wait_for_terminate_and_check(t, pid, WAIT_LOG);
if (r < 0)
continue;
@@ -177,7 +176,7 @@ static int do_execute(
t = hashmap_remove(pids, PID_TO_PTR(pid));
assert(t);
wait_for_terminate_and_warn(t, pid, true);
(void) wait_for_terminate_and_check(t, pid, WAIT_LOG);
}
return 0;
@@ -190,10 +189,9 @@ int execute_directories(
void* const callback_args[_STDOUT_CONSUME_MAX],
char *argv[]) {
pid_t executor_pid;
char *name;
char **dirs = (char**) directories;
_cleanup_close_ int fd = -1;
char *name;
int r;
assert(!strv_isempty(dirs));
@@ -216,23 +214,14 @@ int execute_directories(
* them to finish. Optionally a timeout is applied. If a file with the same name
* exists in more than one directory, the earliest one wins. */
r = safe_fork("(sd-executor)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &executor_pid);
r = safe_fork("(sd-executor)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG|FORK_WAIT, NULL);
if (r < 0)
return log_error_errno(r, "Failed to fork: %m");
return r;
if (r == 0) {
r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv);
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
r = wait_for_terminate_and_warn(name, executor_pid, true);
if (r < 0)
return log_error_errno(r, "Execution failed: %m");
if (r > 0) {
/* non-zero return code from child */
log_error("Forker process failed.");
return -EREMOTEIO;
}
if (!callbacks)
return 0;
+17 -3
View File
@@ -62,16 +62,28 @@ int write_string_stream_ts(
WriteStringFileFlags flags,
struct timespec *ts) {
bool needs_nl;
assert(f);
assert(line);
if (ferror(f))
return -EIO;
needs_nl = !(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n");
if (needs_nl && (flags & WRITE_STRING_FILE_DISABLE_BUFFER)) {
/* If STDIO buffering was disabled, then let's append the newline character to the string itself, so
* that the write goes out in one go, instead of two */
line = strjoina(line, "\n");
needs_nl = false;
}
if (fputs(line, f) == EOF)
return -errno;
if (!(flags & WRITE_STRING_FILE_AVOID_NEWLINE) && !endswith(line, "\n"))
if (needs_nl)
if (fputc('\n', f) == EOF)
return -errno;
@@ -914,14 +926,16 @@ int write_env_file(const char *fname, char **l) {
}
int executable_is_script(const char *path, char **interpreter) {
int r;
_cleanup_free_ char *line = NULL;
int len;
size_t len;
char *ans;
int r;
assert(path);
r = read_one_line_file(path, &line);
if (r == -ENOBUFS) /* First line overly long? if so, then it's not a script */
return 0;
if (r < 0)
return r;
+4
View File
@@ -621,6 +621,10 @@ struct btrfs_ioctl_quota_ctl_args {
# define SO_REUSEPORT 15
#endif
#ifndef SO_PEERGROUPS
# define SO_PEERGROUPS 59
#endif
#ifndef EVIOCREVOKE
# define EVIOCREVOKE _IOW('E', 0x91, int)
#endif
+69 -31
View File
@@ -687,32 +687,43 @@ int wait_for_terminate(pid_t pid, siginfo_t *status) {
* A warning is emitted if the process terminates abnormally,
* and also if it returns non-zero unless check_exit_code is true.
*/
int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code) {
int r;
int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags) {
_cleanup_free_ char *buffer = NULL;
siginfo_t status;
int r, prio;
assert(name);
assert(pid > 1);
if (!name) {
r = get_process_comm(pid, &buffer);
if (r < 0)
log_debug_errno(r, "Failed to acquire process name of " PID_FMT ", ignoring: %m", pid);
else
name = buffer;
}
prio = flags & WAIT_LOG_ABNORMAL ? LOG_ERR : LOG_DEBUG;
r = wait_for_terminate(pid, &status);
if (r < 0)
return log_warning_errno(r, "Failed to wait for %s: %m", name);
return log_full_errno(prio, r, "Failed to wait for %s: %m", strna(name));
if (status.si_code == CLD_EXITED) {
if (status.si_status != 0)
log_full(check_exit_code ? LOG_WARNING : LOG_DEBUG,
"%s failed with error code %i.", name, status.si_status);
if (status.si_status != EXIT_SUCCESS)
log_full(flags & WAIT_LOG_NON_ZERO_EXIT_STATUS ? LOG_ERR : LOG_DEBUG,
"%s failed with exit status %i.", strna(name), status.si_status);
else
log_debug("%s succeeded.", name);
return status.si_status;
} else if (IN_SET(status.si_code, CLD_KILLED, CLD_DUMPED)) {
log_warning("%s terminated by signal %s.", name, signal_to_string(status.si_status));
log_full(prio, "%s terminated by signal %s.", strna(name), signal_to_string(status.si_status));
return -EPROTO;
}
log_warning("%s failed due to unknown reason.", name);
log_full(prio, "%s failed due to unknown reason.", strna(name));
return -EPROTO;
}
@@ -1083,7 +1094,7 @@ int ioprio_parse_priority(const char *s, int *ret) {
static pid_t cached_pid = CACHED_PID_UNSET;
static void reset_cached_pid(void) {
void reset_cached_pid(void) {
/* Invoked in the child after a fork(), i.e. at the first moment the PID changed */
cached_pid = CACHED_PID_UNSET;
}
@@ -1150,46 +1161,72 @@ int safe_fork_full(
pid_t *ret_pid) {
pid_t original_pid, pid;
sigset_t saved_ss;
sigset_t saved_ss, ss;
bool block_signals;
int r;
int prio, r;
/* A wrapper around fork(), that does a couple of important initializations in addition to mere forking. Always
* returns the child's PID in *ret_pid. Returns == 0 in the child, and > 0 in the parent. */
prio = flags & FORK_LOG ? LOG_ERR : LOG_DEBUG;
original_pid = getpid_cached();
block_signals = flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG);
if (flags & (FORK_RESET_SIGNALS|FORK_DEATHSIG)) {
if (block_signals) {
sigset_t ss;
/* We temporarily block all signals, so that the new child has them blocked initially. This way, we can
* be sure that SIGTERMs are not lost we might send to the child. */
/* We temporarily block all signals, so that the new child has them blocked initially. This way, we can be sure
* that SIGTERMs are not lost we might send to the child. */
if (sigfillset(&ss) < 0)
return log_debug_errno(errno, "Failed to reset signal set: %m");
return log_full_errno(prio, errno, "Failed to reset signal set: %m");
if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0)
return log_debug_errno(errno, "Failed to reset signal mask: %m");
block_signals = true;
} else if (flags & FORK_WAIT) {
/* Let's block SIGCHLD at least, so that we can safely watch for the child process */
if (sigemptyset(&ss) < 0)
return log_full_errno(prio, errno, "Failed to clear signal set: %m");
if (sigaddset(&ss, SIGCHLD) < 0)
return log_full_errno(prio, errno, "Failed to add SIGCHLD to signal set: %m");
block_signals = true;
}
pid = fork();
if (block_signals)
if (sigprocmask(SIG_SETMASK, &ss, &saved_ss) < 0)
return log_full_errno(prio, errno, "Failed to set signal mask: %m");
if (flags & FORK_NEW_MOUNTNS)
pid = raw_clone(SIGCHLD|CLONE_NEWNS);
else
pid = fork();
if (pid < 0) {
r = -errno;
if (block_signals) /* undo what we did above */
(void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
return log_debug_errno(r, "Failed to fork: %m");
return log_full_errno(prio, r, "Failed to fork: %m");
}
if (pid > 0) {
/* We are in the parent process */
log_debug("Successfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
if (flags & FORK_WAIT) {
r = wait_for_terminate_and_check(name, pid, (flags & FORK_LOG ? WAIT_LOG : 0));
if (r < 0)
return r;
if (r != EXIT_SUCCESS) /* exit status > 0 should be treated as failure, too */
return -EPROTO;
}
if (block_signals) /* undo what we did above */
(void) sigprocmask(SIG_SETMASK, &saved_ss, NULL);
log_debug("Sucessfully forked off '%s' as PID " PID_FMT ".", strna(name), pid);
if (ret_pid)
*ret_pid = pid;
@@ -1207,31 +1244,32 @@ int safe_fork_full(
if (name) {
r = rename_process(name);
if (r < 0)
log_debug_errno(r, "Failed to rename process, ignoring: %m");
log_full_errno(flags & FORK_LOG ? LOG_WARNING : LOG_DEBUG,
r, "Failed to rename process, ignoring: %m");
}
if (flags & FORK_DEATHSIG)
if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) {
log_debug_errno(errno, "Failed to set death signal: %m");
log_full_errno(prio, errno, "Failed to set death signal: %m");
_exit(EXIT_FAILURE);
}
if (flags & FORK_RESET_SIGNALS) {
r = reset_all_signal_handlers();
if (r < 0) {
log_debug_errno(r, "Failed to reset signal handlers: %m");
log_full_errno(prio, r, "Failed to reset signal handlers: %m");
_exit(EXIT_FAILURE);
}
/* This implicitly undoes the signal mask stuff we did before the fork()ing above */
r = reset_signal_mask();
if (r < 0) {
log_debug_errno(r, "Failed to reset signal mask: %m");
log_full_errno(prio, r, "Failed to reset signal mask: %m");
_exit(EXIT_FAILURE);
}
} else if (block_signals) { /* undo what we did above */
if (sigprocmask(SIG_SETMASK, &saved_ss, NULL) < 0) {
log_debug_errno(errno, "Failed to restore signal mask: %m");
log_full_errno(prio, errno, "Failed to restore signal mask: %m");
_exit(EXIT_FAILURE);
}
}
@@ -1257,7 +1295,7 @@ int safe_fork_full(
r = close_all_fds(except_fds, n_except_fds);
if (r < 0) {
log_debug_errno(r, "Failed to close all file descriptors: %m");
log_full_errno(prio, r, "Failed to close all file descriptors: %m");
_exit(EXIT_FAILURE);
}
}
@@ -1271,7 +1309,7 @@ int safe_fork_full(
if (flags & FORK_NULL_STDIO) {
r = make_null_stdio();
if (r < 0) {
log_debug_errno(r, "Failed to connect stdin/stdout to /dev/null: %m");
log_full_errno(prio, r, "Failed to connect stdin/stdout to /dev/null: %m");
_exit(EXIT_FAILURE);
}
}
+14 -1
View File
@@ -61,7 +61,16 @@ int get_process_environ(pid_t pid, char **environ);
int get_process_ppid(pid_t pid, pid_t *ppid);
int wait_for_terminate(pid_t pid, siginfo_t *status);
int wait_for_terminate_and_warn(const char *name, pid_t pid, bool check_exit_code);
typedef enum WaitFlags {
WAIT_LOG_ABNORMAL = 1U << 0,
WAIT_LOG_NON_ZERO_EXIT_STATUS = 1U << 1,
/* A shortcut for requesting the most complete logging */
WAIT_LOG = WAIT_LOG_ABNORMAL|WAIT_LOG_NON_ZERO_EXIT_STATUS,
} WaitFlags;
int wait_for_terminate_and_check(const char *name, pid_t pid, WaitFlags flags);
int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout);
void sigkill_wait(pid_t pid);
@@ -147,6 +156,7 @@ static inline int sched_policy_to_string_alloc_with_check(int n, char **s) {
int ioprio_parse_priority(const char *s, int *ret);
pid_t getpid_cached(void);
void reset_cached_pid(void);
int must_be_root(void);
@@ -156,6 +166,9 @@ typedef enum ForkFlags {
FORK_DEATHSIG = 1U << 2,
FORK_NULL_STDIO = 1U << 3,
FORK_REOPEN_LOG = 1U << 4,
FORK_LOG = 1U << 5,
FORK_WAIT = 1U << 6,
FORK_NEW_MOUNTNS = 1U << 7,
} ForkFlags;
int safe_fork_full(const char *name, const int except_fds[], size_t n_except_fds, ForkFlags flags, pid_t *ret_pid);
+22 -20
View File
@@ -30,28 +30,27 @@
* raw_clone() - uses clone to create a new process with clone flags
* @flags: Flags to pass to the clone system call
*
* Uses the clone system call to create a new process with the cloning
* flags and termination signal passed in the flags parameter. Opposed
* to glibc's clone funtion, using this function does not set up a
* separate stack for the child, but relies on copy-on-write semantics
* on the one stack at a common virtual address, just as fork does.
* Uses the clone system call to create a new process with the cloning flags and termination signal passed in the flags
* parameter. Opposed to glibc's clone funtion, using this function does not set up a separate stack for the child, but
* relies on copy-on-write semantics on the one stack at a common virtual address, just as fork does.
*
* To obtain copy-on-write semantics, flags must not contain CLONE_VM,
* and thus CLONE_THREAD and CLONE_SIGHAND (which require CLONE_VM) are
* not usabale.
* Additionally, as this function does not pass the ptid, newtls and ctid
* parameters to the kernel, flags must not contain CLONE_PARENT_SETTID,
* CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS.
* To obtain copy-on-write semantics, flags must not contain CLONE_VM, and thus CLONE_THREAD and CLONE_SIGHAND (which
* require CLONE_VM) are not usable.
*
* Additionally, as this function does not pass the ptid, newtls and ctid parameters to the kernel, flags must not
* contain CLONE_PARENT_SETTID, CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID or CLONE_SETTLS.
*
* Returns: 0 in the child process and the child process id in the parent.
*/
static inline int raw_clone(unsigned long flags) {
static inline pid_t raw_clone(unsigned long flags) {
pid_t ret;
assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|
CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0);
#if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
/* On s390/s390x and cris the order of the first and second arguments
* of the raw clone() system call is reversed. */
return (int) syscall(__NR_clone, NULL, flags);
ret = (pid_t) syscall(__NR_clone, NULL, flags);
#elif defined(__sparc__) && defined(__arch64__)
{
/**
@@ -60,8 +59,8 @@ static inline int raw_clone(unsigned long flags) {
* %o1. Inline assembly is needed to get the flag returned
* in %o1.
*/
int in_child;
int child_pid;
int in_child, child_pid;
asm volatile("mov %2, %%g1\n\t"
"mov %3, %%o0\n\t"
"mov 0 , %%o1\n\t"
@@ -71,12 +70,15 @@ static inline int raw_clone(unsigned long flags) {
"=r"(in_child), "=r"(child_pid) :
"i"(__NR_clone), "r"(flags) :
"%o1", "%o0", "%g1" );
if (in_child)
return 0;
else
return child_pid;
ret = in_child ? 0 : child_pid;
}
#else
return (int) syscall(__NR_clone, flags, NULL);
ret = (pid_t) syscall(__NR_clone, flags, NULL);
#endif
if (ret == 0)
reset_cached_pid();
return ret;
}
+49 -27
View File
@@ -967,58 +967,80 @@ int getpeercred(int fd, struct ucred *ucred) {
if (n != sizeof(struct ucred))
return -EIO;
/* Check if the data is actually useful and not suppressed due
* to namespacing issues */
if (u.pid <= 0)
return -ENODATA;
if (u.uid == UID_INVALID)
return -ENODATA;
if (u.gid == GID_INVALID)
/* Check if the data is actually useful and not suppressed due to namespacing issues */
if (!pid_is_valid(u.pid))
return -ENODATA;
/* Note that we don't check UID/GID here, as namespace translation works differently there: instead of
* receiving in "invalid" user/group we get the overflow UID/GID. */
*ucred = u;
return 0;
}
int getpeersec(int fd, char **ret) {
_cleanup_free_ char *s = NULL;
socklen_t n = 64;
char *s;
int r;
assert(fd >= 0);
assert(ret);
s = new0(char, n);
if (!s)
return -ENOMEM;
for (;;) {
s = new0(char, n+1);
if (!s)
return -ENOMEM;
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
if (r < 0) {
free(s);
if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n) >= 0)
break;
if (errno != ERANGE)
return -errno;
s = new0(char, n);
if (!s)
return -ENOMEM;
r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
if (r < 0) {
free(s);
return -errno;
}
s = mfree(s);
}
if (isempty(s)) {
free(s);
if (isempty(s))
return -EOPNOTSUPP;
}
*ret = s;
s = NULL;
return 0;
}
int getpeergroups(int fd, gid_t **ret) {
socklen_t n = sizeof(gid_t) * 64;
_cleanup_free_ gid_t *d = NULL;
assert(fd);
assert(ret);
for (;;) {
d = malloc(n);
if (!d)
return -ENOMEM;
if (getsockopt(fd, SOL_SOCKET, SO_PEERGROUPS, d, &n) >= 0)
break;
if (errno != ERANGE)
return -errno;
d = mfree(d);
}
assert_se(n % sizeof(gid_t) == 0);
n /= sizeof(gid_t);
if ((socklen_t) (int) n != n)
return -E2BIG;
*ret = d;
d = NULL;
return (int) n;
}
int send_one_fd_sa(
int transport_fd,
int fd,
+1
View File
@@ -138,6 +138,7 @@ bool address_label_valid(const char *p);
int getpeercred(int fd, struct ucred *ucred);
int getpeersec(int fd, char **ret);
int getpeergroups(int fd, gid_t **ret);
int send_one_fd_sa(int transport_fd,
int fd,
+4 -6
View File
@@ -1093,7 +1093,6 @@ int ptsname_namespace(int pty, char **ret) {
int openpt_in_namespace(pid_t pid, int flags) {
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
_cleanup_close_pair_ int pair[2] = { -1, -1 };
siginfo_t si;
pid_t child;
int r;
@@ -1133,10 +1132,10 @@ int openpt_in_namespace(pid_t pid, int flags) {
pair[1] = safe_close(pair[1]);
r = wait_for_terminate(child, &si);
r = wait_for_terminate_and_check("(sd-openpt)", child, 0);
if (r < 0)
return r;
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
if (r != EXIT_SUCCESS)
return -EIO;
return receive_one_fd(pair[0], 0);
@@ -1145,7 +1144,6 @@ int openpt_in_namespace(pid_t pid, int flags) {
int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
_cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
_cleanup_close_pair_ int pair[2] = { -1, -1 };
siginfo_t si;
pid_t child;
int r;
@@ -1180,10 +1178,10 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
pair[1] = safe_close(pair[1]);
r = wait_for_terminate(child, &si);
r = wait_for_terminate_and_check("(sd-terminal)", child, 0);
if (r < 0)
return r;
if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
if (r != EXIT_SUCCESS)
return -EIO;
return receive_one_fd(pair[0], 0);
+1 -8
View File
@@ -886,7 +886,6 @@ typedef struct ParseTimestampResult {
int parse_timestamp(const char *t, usec_t *usec) {
char *last_space, *tz = NULL;
ParseTimestampResult *shared, tmp;
pid_t pid;
int r;
last_space = strrchr(t, ' ');
@@ -900,7 +899,7 @@ int parse_timestamp(const char *t, usec_t *usec) {
if (shared == MAP_FAILED)
return negative_errno();
r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG, &pid);
r = safe_fork("(sd-timestamp)", FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_WAIT, NULL);
if (r < 0) {
(void) munmap(shared, sizeof *shared);
return r;
@@ -928,12 +927,6 @@ int parse_timestamp(const char *t, usec_t *usec) {
_exit(EXIT_SUCCESS);
}
r = wait_for_terminate(pid, NULL);
if (r < 0) {
(void) munmap(shared, sizeof *shared);
return r;
}
tmp = *shared;
if (munmap(shared, sizeof *shared) != 0)
return negative_errno();
+3 -2
View File
@@ -358,8 +358,9 @@ char* gid_to_name(gid_t gid) {
}
int in_gid(gid_t gid) {
long ngroups_max;
gid_t *gids;
int ngroups_max, r, i;
int r, i;
if (getgid() == gid)
return 1;
@@ -373,7 +374,7 @@ int in_gid(gid_t gid) {
ngroups_max = sysconf(_SC_NGROUPS_MAX);
assert(ngroups_max > 0);
gids = alloca(sizeof(gid_t) * ngroups_max);
gids = newa(gid_t, ngroups_max);
r = getgroups(ngroups_max, gids);
if (r < 0)