1*71db0c75SAndroid Build Coastguard Worker //===-- Linux implementation of posix_spawn -------------------------------===//
2*71db0c75SAndroid Build Coastguard Worker //
3*71db0c75SAndroid Build Coastguard Worker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*71db0c75SAndroid Build Coastguard Worker // See https://llvm.org/LICENSE.txt for license information.
5*71db0c75SAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*71db0c75SAndroid Build Coastguard Worker //
7*71db0c75SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*71db0c75SAndroid Build Coastguard Worker
9*71db0c75SAndroid Build Coastguard Worker #include "src/spawn/posix_spawn.h"
10*71db0c75SAndroid Build Coastguard Worker
11*71db0c75SAndroid Build Coastguard Worker #include "src/__support/CPP/optional.h"
12*71db0c75SAndroid Build Coastguard Worker #include "src/__support/OSUtil/syscall.h" // For internal syscall function.
13*71db0c75SAndroid Build Coastguard Worker #include "src/__support/common.h"
14*71db0c75SAndroid Build Coastguard Worker #include "src/__support/macros/config.h"
15*71db0c75SAndroid Build Coastguard Worker #include "src/spawn/file_actions.h"
16*71db0c75SAndroid Build Coastguard Worker
17*71db0c75SAndroid Build Coastguard Worker #include "hdr/fcntl_macros.h"
18*71db0c75SAndroid Build Coastguard Worker #include "hdr/types/mode_t.h"
19*71db0c75SAndroid Build Coastguard Worker #include <signal.h> // For SIGCHLD
20*71db0c75SAndroid Build Coastguard Worker #include <spawn.h>
21*71db0c75SAndroid Build Coastguard Worker #include <sys/syscall.h> // For syscall numbers.
22*71db0c75SAndroid Build Coastguard Worker
23*71db0c75SAndroid Build Coastguard Worker namespace LIBC_NAMESPACE_DECL {
24*71db0c75SAndroid Build Coastguard Worker
25*71db0c75SAndroid Build Coastguard Worker namespace {
26*71db0c75SAndroid Build Coastguard Worker
fork()27*71db0c75SAndroid Build Coastguard Worker pid_t fork() {
28*71db0c75SAndroid Build Coastguard Worker // TODO: Use only the clone syscall and use a sperate small stack in the child
29*71db0c75SAndroid Build Coastguard Worker // to avoid duplicating the complete stack from the parent. A new stack will
30*71db0c75SAndroid Build Coastguard Worker // be created on exec anyway so duplicating the full stack is unnecessary.
31*71db0c75SAndroid Build Coastguard Worker #ifdef SYS_fork
32*71db0c75SAndroid Build Coastguard Worker return LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_fork);
33*71db0c75SAndroid Build Coastguard Worker #elif defined(SYS_clone)
34*71db0c75SAndroid Build Coastguard Worker return LIBC_NAMESPACE::syscall_impl<pid_t>(SYS_clone, SIGCHLD, 0);
35*71db0c75SAndroid Build Coastguard Worker #else
36*71db0c75SAndroid Build Coastguard Worker #error "fork or clone syscalls not available."
37*71db0c75SAndroid Build Coastguard Worker #endif
38*71db0c75SAndroid Build Coastguard Worker }
39*71db0c75SAndroid Build Coastguard Worker
open(const char * path,int oflags,mode_t mode)40*71db0c75SAndroid Build Coastguard Worker cpp::optional<int> open(const char *path, int oflags, mode_t mode) {
41*71db0c75SAndroid Build Coastguard Worker #ifdef SYS_open
42*71db0c75SAndroid Build Coastguard Worker int fd = LIBC_NAMESPACE::syscall_impl<int>(SYS_open, path, oflags, mode);
43*71db0c75SAndroid Build Coastguard Worker #else
44*71db0c75SAndroid Build Coastguard Worker int fd = LIBC_NAMESPACE::syscall_impl<int>(SYS_openat, AT_FDCWD, path, oflags,
45*71db0c75SAndroid Build Coastguard Worker mode);
46*71db0c75SAndroid Build Coastguard Worker #endif
47*71db0c75SAndroid Build Coastguard Worker if (fd > 0)
48*71db0c75SAndroid Build Coastguard Worker return fd;
49*71db0c75SAndroid Build Coastguard Worker // The open function is called as part of the child process' preparatory
50*71db0c75SAndroid Build Coastguard Worker // steps. If an open fails, the child process just exits. So, unlike
51*71db0c75SAndroid Build Coastguard Worker // the public open function, we do not need to set errno here.
52*71db0c75SAndroid Build Coastguard Worker return cpp::nullopt;
53*71db0c75SAndroid Build Coastguard Worker }
54*71db0c75SAndroid Build Coastguard Worker
close(int fd)55*71db0c75SAndroid Build Coastguard Worker void close(int fd) { LIBC_NAMESPACE::syscall_impl<long>(SYS_close, fd); }
56*71db0c75SAndroid Build Coastguard Worker
57*71db0c75SAndroid Build Coastguard Worker // We use dup3 if dup2 is not available, similar to our implementation of dup2
dup2(int fd,int newfd)58*71db0c75SAndroid Build Coastguard Worker bool dup2(int fd, int newfd) {
59*71db0c75SAndroid Build Coastguard Worker #ifdef SYS_dup2
60*71db0c75SAndroid Build Coastguard Worker int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_dup2, fd, newfd);
61*71db0c75SAndroid Build Coastguard Worker #elif defined(SYS_dup3)
62*71db0c75SAndroid Build Coastguard Worker int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_dup3, fd, newfd, 0);
63*71db0c75SAndroid Build Coastguard Worker #else
64*71db0c75SAndroid Build Coastguard Worker #error "dup2 and dup3 syscalls not available."
65*71db0c75SAndroid Build Coastguard Worker #endif
66*71db0c75SAndroid Build Coastguard Worker return ret < 0 ? false : true;
67*71db0c75SAndroid Build Coastguard Worker }
68*71db0c75SAndroid Build Coastguard Worker
69*71db0c75SAndroid Build Coastguard Worker // All exits from child_process are error exits. So, we use a simple
70*71db0c75SAndroid Build Coastguard Worker // exit implementation which exits with code 127.
exit()71*71db0c75SAndroid Build Coastguard Worker void exit() {
72*71db0c75SAndroid Build Coastguard Worker for (;;) {
73*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::syscall_impl<long>(SYS_exit_group, 127);
74*71db0c75SAndroid Build Coastguard Worker LIBC_NAMESPACE::syscall_impl<long>(SYS_exit, 127);
75*71db0c75SAndroid Build Coastguard Worker }
76*71db0c75SAndroid Build Coastguard Worker }
77*71db0c75SAndroid Build Coastguard Worker
child_process(const char * __restrict path,const posix_spawn_file_actions_t * file_actions,const posix_spawnattr_t * __restrict,char * const * __restrict argv,char * const * __restrict envp)78*71db0c75SAndroid Build Coastguard Worker void child_process(const char *__restrict path,
79*71db0c75SAndroid Build Coastguard Worker const posix_spawn_file_actions_t *file_actions,
80*71db0c75SAndroid Build Coastguard Worker const posix_spawnattr_t *__restrict, // For now unused
81*71db0c75SAndroid Build Coastguard Worker char *const *__restrict argv, char *const *__restrict envp) {
82*71db0c75SAndroid Build Coastguard Worker // TODO: In the code below, the child_process just exits on error during
83*71db0c75SAndroid Build Coastguard Worker // processing |file_actions| and |attr|. The correct way would be to exit
84*71db0c75SAndroid Build Coastguard Worker // after conveying the information about the failure to the parent process
85*71db0c75SAndroid Build Coastguard Worker // (via a pipe for example).
86*71db0c75SAndroid Build Coastguard Worker // TODO: Handle |attr|.
87*71db0c75SAndroid Build Coastguard Worker
88*71db0c75SAndroid Build Coastguard Worker if (file_actions != nullptr) {
89*71db0c75SAndroid Build Coastguard Worker auto *act = reinterpret_cast<BaseSpawnFileAction *>(file_actions->__front);
90*71db0c75SAndroid Build Coastguard Worker while (act != nullptr) {
91*71db0c75SAndroid Build Coastguard Worker switch (act->type) {
92*71db0c75SAndroid Build Coastguard Worker case BaseSpawnFileAction::OPEN: {
93*71db0c75SAndroid Build Coastguard Worker auto *open_act = reinterpret_cast<SpawnFileOpenAction *>(act);
94*71db0c75SAndroid Build Coastguard Worker auto fd = open(open_act->path, open_act->oflag, open_act->mode);
95*71db0c75SAndroid Build Coastguard Worker if (!fd)
96*71db0c75SAndroid Build Coastguard Worker exit();
97*71db0c75SAndroid Build Coastguard Worker int actual_fd = *fd;
98*71db0c75SAndroid Build Coastguard Worker if (actual_fd != open_act->fd) {
99*71db0c75SAndroid Build Coastguard Worker bool dup2_result = dup2(actual_fd, open_act->fd);
100*71db0c75SAndroid Build Coastguard Worker close(actual_fd); // The old fd is not needed anymore.
101*71db0c75SAndroid Build Coastguard Worker if (!dup2_result)
102*71db0c75SAndroid Build Coastguard Worker exit();
103*71db0c75SAndroid Build Coastguard Worker }
104*71db0c75SAndroid Build Coastguard Worker break;
105*71db0c75SAndroid Build Coastguard Worker }
106*71db0c75SAndroid Build Coastguard Worker case BaseSpawnFileAction::CLOSE: {
107*71db0c75SAndroid Build Coastguard Worker auto *close_act = reinterpret_cast<SpawnFileCloseAction *>(act);
108*71db0c75SAndroid Build Coastguard Worker close(close_act->fd);
109*71db0c75SAndroid Build Coastguard Worker break;
110*71db0c75SAndroid Build Coastguard Worker }
111*71db0c75SAndroid Build Coastguard Worker case BaseSpawnFileAction::DUP2: {
112*71db0c75SAndroid Build Coastguard Worker auto *dup2_act = reinterpret_cast<SpawnFileDup2Action *>(act);
113*71db0c75SAndroid Build Coastguard Worker if (!dup2(dup2_act->fd, dup2_act->newfd))
114*71db0c75SAndroid Build Coastguard Worker exit();
115*71db0c75SAndroid Build Coastguard Worker break;
116*71db0c75SAndroid Build Coastguard Worker }
117*71db0c75SAndroid Build Coastguard Worker }
118*71db0c75SAndroid Build Coastguard Worker act = act->next;
119*71db0c75SAndroid Build Coastguard Worker }
120*71db0c75SAndroid Build Coastguard Worker }
121*71db0c75SAndroid Build Coastguard Worker
122*71db0c75SAndroid Build Coastguard Worker if (LIBC_NAMESPACE::syscall_impl<long>(SYS_execve, path, argv, envp) < 0)
123*71db0c75SAndroid Build Coastguard Worker exit();
124*71db0c75SAndroid Build Coastguard Worker }
125*71db0c75SAndroid Build Coastguard Worker
126*71db0c75SAndroid Build Coastguard Worker } // anonymous namespace
127*71db0c75SAndroid Build Coastguard Worker
128*71db0c75SAndroid Build Coastguard Worker LLVM_LIBC_FUNCTION(int, posix_spawn,
129*71db0c75SAndroid Build Coastguard Worker (pid_t *__restrict pid, const char *__restrict path,
130*71db0c75SAndroid Build Coastguard Worker const posix_spawn_file_actions_t *file_actions,
131*71db0c75SAndroid Build Coastguard Worker const posix_spawnattr_t *__restrict attr,
132*71db0c75SAndroid Build Coastguard Worker char *const *__restrict argv,
133*71db0c75SAndroid Build Coastguard Worker char *const *__restrict envp)) {
134*71db0c75SAndroid Build Coastguard Worker pid_t cpid = fork();
135*71db0c75SAndroid Build Coastguard Worker if (cpid == 0)
136*71db0c75SAndroid Build Coastguard Worker child_process(path, file_actions, attr, argv, envp);
137*71db0c75SAndroid Build Coastguard Worker else if (cpid < 0)
138*71db0c75SAndroid Build Coastguard Worker return -cpid;
139*71db0c75SAndroid Build Coastguard Worker
140*71db0c75SAndroid Build Coastguard Worker if (pid != nullptr)
141*71db0c75SAndroid Build Coastguard Worker *pid = cpid;
142*71db0c75SAndroid Build Coastguard Worker
143*71db0c75SAndroid Build Coastguard Worker // TODO: Before returning, one should wait for the child_process to startup
144*71db0c75SAndroid Build Coastguard Worker // successfully. For now, we will just return. Future changes will add proper
145*71db0c75SAndroid Build Coastguard Worker // wait (using pipes for example).
146*71db0c75SAndroid Build Coastguard Worker
147*71db0c75SAndroid Build Coastguard Worker return 0;
148*71db0c75SAndroid Build Coastguard Worker }
149*71db0c75SAndroid Build Coastguard Worker
150*71db0c75SAndroid Build Coastguard Worker } // namespace LIBC_NAMESPACE_DECL
151