From: Lennart Poettering Date: Fri, 29 Dec 2017 15:45:04 +0000 (+0100) Subject: raw-clone: beef up raw_clone() wrapper a bit X-Git-Tag: v237~146^2~23 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=799a960d1f80c58fd982b3c248906cd4791a69fa;p=thirdparty%2Fsystemd.git raw-clone: beef up raw_clone() wrapper a bit First of all, let's return pid_t, which appears to be the correct type given that we return PIDs, and it#s what fork() uses too. Most importantly though, flush out our PID cache, so that the call becomes compatible with our getpid_cached() logic. --- diff --git a/src/basic/process-util.c b/src/basic/process-util.c index 7da22f4a9db..9a42ce34fc4 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -1083,7 +1083,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; } diff --git a/src/basic/process-util.h b/src/basic/process-util.h index b20e527af77..fa58c69464d 100644 --- a/src/basic/process-util.h +++ b/src/basic/process-util.h @@ -147,6 +147,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); diff --git a/src/basic/raw-clone.h b/src/basic/raw-clone.h index f01b73a8feb..8c95380305c 100644 --- a/src/basic/raw-clone.h +++ b/src/basic/raw-clone.h @@ -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; }