1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker * Copyright (C) 2008 The Android Open Source Project
3*598139dcSAndroid Build Coastguard Worker *
4*598139dcSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*598139dcSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*598139dcSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*598139dcSAndroid Build Coastguard Worker *
8*598139dcSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*598139dcSAndroid Build Coastguard Worker *
10*598139dcSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*598139dcSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*598139dcSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*598139dcSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*598139dcSAndroid Build Coastguard Worker * limitations under the License.
15*598139dcSAndroid Build Coastguard Worker */
16*598139dcSAndroid Build Coastguard Worker
17*598139dcSAndroid Build Coastguard Worker #include <errno.h>
18*598139dcSAndroid Build Coastguard Worker #include <fcntl.h>
19*598139dcSAndroid Build Coastguard Worker #include <libgen.h>
20*598139dcSAndroid Build Coastguard Worker #include <poll.h>
21*598139dcSAndroid Build Coastguard Worker #include <pthread.h>
22*598139dcSAndroid Build Coastguard Worker #include <stdio.h>
23*598139dcSAndroid Build Coastguard Worker #include <stdlib.h>
24*598139dcSAndroid Build Coastguard Worker #include <string.h>
25*598139dcSAndroid Build Coastguard Worker #include <sys/socket.h>
26*598139dcSAndroid Build Coastguard Worker #include <sys/types.h>
27*598139dcSAndroid Build Coastguard Worker #include <sys/wait.h>
28*598139dcSAndroid Build Coastguard Worker #include <unistd.h>
29*598139dcSAndroid Build Coastguard Worker
30*598139dcSAndroid Build Coastguard Worker #include <algorithm>
31*598139dcSAndroid Build Coastguard Worker
32*598139dcSAndroid Build Coastguard Worker #include <android-base/macros.h>
33*598139dcSAndroid Build Coastguard Worker #include <cutils/klog.h>
34*598139dcSAndroid Build Coastguard Worker #include <log/log.h>
35*598139dcSAndroid Build Coastguard Worker #include <logwrap/logwrap.h>
36*598139dcSAndroid Build Coastguard Worker
37*598139dcSAndroid Build Coastguard Worker static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER;
38*598139dcSAndroid Build Coastguard Worker // Protected by fd_mutex. These signals must be blocked while modifying as well.
39*598139dcSAndroid Build Coastguard Worker static pid_t child_pid;
40*598139dcSAndroid Build Coastguard Worker static struct sigaction old_int;
41*598139dcSAndroid Build Coastguard Worker static struct sigaction old_quit;
42*598139dcSAndroid Build Coastguard Worker static struct sigaction old_hup;
43*598139dcSAndroid Build Coastguard Worker
44*598139dcSAndroid Build Coastguard Worker #define ERROR(fmt, args...) \
45*598139dcSAndroid Build Coastguard Worker do { \
46*598139dcSAndroid Build Coastguard Worker fprintf(stderr, fmt, ##args); \
47*598139dcSAndroid Build Coastguard Worker ALOG(LOG_ERROR, "logwrapper", fmt, ##args); \
48*598139dcSAndroid Build Coastguard Worker } while (0)
49*598139dcSAndroid Build Coastguard Worker
50*598139dcSAndroid Build Coastguard Worker #define FATAL_CHILD(fmt, args...) \
51*598139dcSAndroid Build Coastguard Worker do { \
52*598139dcSAndroid Build Coastguard Worker ERROR(fmt, ##args); \
53*598139dcSAndroid Build Coastguard Worker _exit(-1); \
54*598139dcSAndroid Build Coastguard Worker } while (0)
55*598139dcSAndroid Build Coastguard Worker
56*598139dcSAndroid Build Coastguard Worker #define MAX_KLOG_TAG 16
57*598139dcSAndroid Build Coastguard Worker
58*598139dcSAndroid Build Coastguard Worker /* This is a simple buffer that holds up to the first beginning_buf->buf_size
59*598139dcSAndroid Build Coastguard Worker * bytes of output from a command.
60*598139dcSAndroid Build Coastguard Worker */
61*598139dcSAndroid Build Coastguard Worker #define BEGINNING_BUF_SIZE 0x1000
62*598139dcSAndroid Build Coastguard Worker struct beginning_buf {
63*598139dcSAndroid Build Coastguard Worker char* buf;
64*598139dcSAndroid Build Coastguard Worker size_t alloc_len;
65*598139dcSAndroid Build Coastguard Worker /* buf_size is the usable space, which is one less than the allocated size */
66*598139dcSAndroid Build Coastguard Worker size_t buf_size;
67*598139dcSAndroid Build Coastguard Worker size_t used_len;
68*598139dcSAndroid Build Coastguard Worker };
69*598139dcSAndroid Build Coastguard Worker
70*598139dcSAndroid Build Coastguard Worker /* This is a circular buf that holds up to the last ending_buf->buf_size bytes
71*598139dcSAndroid Build Coastguard Worker * of output from a command after the first beginning_buf->buf_size bytes
72*598139dcSAndroid Build Coastguard Worker * (which are held in beginning_buf above).
73*598139dcSAndroid Build Coastguard Worker */
74*598139dcSAndroid Build Coastguard Worker #define ENDING_BUF_SIZE 0x1000
75*598139dcSAndroid Build Coastguard Worker struct ending_buf {
76*598139dcSAndroid Build Coastguard Worker char* buf;
77*598139dcSAndroid Build Coastguard Worker ssize_t alloc_len;
78*598139dcSAndroid Build Coastguard Worker /* buf_size is the usable space, which is one less than the allocated size */
79*598139dcSAndroid Build Coastguard Worker ssize_t buf_size;
80*598139dcSAndroid Build Coastguard Worker ssize_t used_len;
81*598139dcSAndroid Build Coastguard Worker /* read and write offsets into the circular buffer */
82*598139dcSAndroid Build Coastguard Worker int read;
83*598139dcSAndroid Build Coastguard Worker int write;
84*598139dcSAndroid Build Coastguard Worker };
85*598139dcSAndroid Build Coastguard Worker
86*598139dcSAndroid Build Coastguard Worker /* A structure to hold all the abbreviated buf data */
87*598139dcSAndroid Build Coastguard Worker struct abbr_buf {
88*598139dcSAndroid Build Coastguard Worker struct beginning_buf b_buf;
89*598139dcSAndroid Build Coastguard Worker struct ending_buf e_buf;
90*598139dcSAndroid Build Coastguard Worker int beginning_buf_full;
91*598139dcSAndroid Build Coastguard Worker };
92*598139dcSAndroid Build Coastguard Worker
93*598139dcSAndroid Build Coastguard Worker /* Collect all the various bits of info needed for logging in one place. */
94*598139dcSAndroid Build Coastguard Worker struct log_info {
95*598139dcSAndroid Build Coastguard Worker int log_target;
96*598139dcSAndroid Build Coastguard Worker char klog_fmt[MAX_KLOG_TAG * 2];
97*598139dcSAndroid Build Coastguard Worker const char* btag;
98*598139dcSAndroid Build Coastguard Worker bool abbreviated;
99*598139dcSAndroid Build Coastguard Worker FILE* fp;
100*598139dcSAndroid Build Coastguard Worker struct abbr_buf a_buf;
101*598139dcSAndroid Build Coastguard Worker };
102*598139dcSAndroid Build Coastguard Worker
103*598139dcSAndroid Build Coastguard Worker /* Forware declaration */
104*598139dcSAndroid Build Coastguard Worker static void add_line_to_abbr_buf(struct abbr_buf* a_buf, char* linebuf, int linelen);
105*598139dcSAndroid Build Coastguard Worker
106*598139dcSAndroid Build Coastguard Worker /* Return 0 on success, and 1 when full */
add_line_to_linear_buf(struct beginning_buf * b_buf,char * line,ssize_t line_len)107*598139dcSAndroid Build Coastguard Worker static int add_line_to_linear_buf(struct beginning_buf* b_buf, char* line, ssize_t line_len) {
108*598139dcSAndroid Build Coastguard Worker int full = 0;
109*598139dcSAndroid Build Coastguard Worker
110*598139dcSAndroid Build Coastguard Worker if ((line_len + b_buf->used_len) > b_buf->buf_size) {
111*598139dcSAndroid Build Coastguard Worker full = 1;
112*598139dcSAndroid Build Coastguard Worker } else {
113*598139dcSAndroid Build Coastguard Worker /* Add to the end of the buf */
114*598139dcSAndroid Build Coastguard Worker memcpy(b_buf->buf + b_buf->used_len, line, line_len);
115*598139dcSAndroid Build Coastguard Worker b_buf->used_len += line_len;
116*598139dcSAndroid Build Coastguard Worker }
117*598139dcSAndroid Build Coastguard Worker
118*598139dcSAndroid Build Coastguard Worker return full;
119*598139dcSAndroid Build Coastguard Worker }
120*598139dcSAndroid Build Coastguard Worker
add_line_to_circular_buf(struct ending_buf * e_buf,char * line,ssize_t line_len)121*598139dcSAndroid Build Coastguard Worker static void add_line_to_circular_buf(struct ending_buf* e_buf, char* line, ssize_t line_len) {
122*598139dcSAndroid Build Coastguard Worker ssize_t free_len;
123*598139dcSAndroid Build Coastguard Worker ssize_t needed_space;
124*598139dcSAndroid Build Coastguard Worker int cnt;
125*598139dcSAndroid Build Coastguard Worker
126*598139dcSAndroid Build Coastguard Worker if (e_buf->buf == nullptr) {
127*598139dcSAndroid Build Coastguard Worker return;
128*598139dcSAndroid Build Coastguard Worker }
129*598139dcSAndroid Build Coastguard Worker
130*598139dcSAndroid Build Coastguard Worker if (line_len > e_buf->buf_size) {
131*598139dcSAndroid Build Coastguard Worker return;
132*598139dcSAndroid Build Coastguard Worker }
133*598139dcSAndroid Build Coastguard Worker
134*598139dcSAndroid Build Coastguard Worker free_len = e_buf->buf_size - e_buf->used_len;
135*598139dcSAndroid Build Coastguard Worker
136*598139dcSAndroid Build Coastguard Worker if (line_len > free_len) {
137*598139dcSAndroid Build Coastguard Worker /* remove oldest entries at read, and move read to make
138*598139dcSAndroid Build Coastguard Worker * room for the new string */
139*598139dcSAndroid Build Coastguard Worker needed_space = line_len - free_len;
140*598139dcSAndroid Build Coastguard Worker e_buf->read = (e_buf->read + needed_space) % e_buf->buf_size;
141*598139dcSAndroid Build Coastguard Worker e_buf->used_len -= needed_space;
142*598139dcSAndroid Build Coastguard Worker }
143*598139dcSAndroid Build Coastguard Worker
144*598139dcSAndroid Build Coastguard Worker /* Copy the line into the circular buffer, dealing with possible
145*598139dcSAndroid Build Coastguard Worker * wraparound.
146*598139dcSAndroid Build Coastguard Worker */
147*598139dcSAndroid Build Coastguard Worker cnt = std::min(line_len, e_buf->buf_size - e_buf->write);
148*598139dcSAndroid Build Coastguard Worker memcpy(e_buf->buf + e_buf->write, line, cnt);
149*598139dcSAndroid Build Coastguard Worker if (cnt < line_len) {
150*598139dcSAndroid Build Coastguard Worker memcpy(e_buf->buf, line + cnt, line_len - cnt);
151*598139dcSAndroid Build Coastguard Worker }
152*598139dcSAndroid Build Coastguard Worker e_buf->used_len += line_len;
153*598139dcSAndroid Build Coastguard Worker e_buf->write = (e_buf->write + line_len) % e_buf->buf_size;
154*598139dcSAndroid Build Coastguard Worker }
155*598139dcSAndroid Build Coastguard Worker
156*598139dcSAndroid Build Coastguard Worker /* Log directly to the specified log */
do_log_line(struct log_info * log_info,const char * line)157*598139dcSAndroid Build Coastguard Worker static void do_log_line(struct log_info* log_info, const char* line) {
158*598139dcSAndroid Build Coastguard Worker if (log_info->log_target & LOG_KLOG) {
159*598139dcSAndroid Build Coastguard Worker klog_write(6, log_info->klog_fmt, line);
160*598139dcSAndroid Build Coastguard Worker }
161*598139dcSAndroid Build Coastguard Worker if (log_info->log_target & LOG_ALOG) {
162*598139dcSAndroid Build Coastguard Worker ALOG(LOG_INFO, log_info->btag, "%s", line);
163*598139dcSAndroid Build Coastguard Worker }
164*598139dcSAndroid Build Coastguard Worker if (log_info->fp) {
165*598139dcSAndroid Build Coastguard Worker fprintf(log_info->fp, "%s\n", line);
166*598139dcSAndroid Build Coastguard Worker }
167*598139dcSAndroid Build Coastguard Worker }
168*598139dcSAndroid Build Coastguard Worker
169*598139dcSAndroid Build Coastguard Worker /* Log to either the abbreviated buf, or directly to the specified log
170*598139dcSAndroid Build Coastguard Worker * via do_log_line() above.
171*598139dcSAndroid Build Coastguard Worker */
log_line(struct log_info * log_info,char * line,int len)172*598139dcSAndroid Build Coastguard Worker static void log_line(struct log_info* log_info, char* line, int len) {
173*598139dcSAndroid Build Coastguard Worker if (log_info->abbreviated) {
174*598139dcSAndroid Build Coastguard Worker add_line_to_abbr_buf(&log_info->a_buf, line, len);
175*598139dcSAndroid Build Coastguard Worker } else {
176*598139dcSAndroid Build Coastguard Worker do_log_line(log_info, line);
177*598139dcSAndroid Build Coastguard Worker }
178*598139dcSAndroid Build Coastguard Worker }
179*598139dcSAndroid Build Coastguard Worker
180*598139dcSAndroid Build Coastguard Worker /*
181*598139dcSAndroid Build Coastguard Worker * The kernel will take a maximum of 1024 bytes in any single write to
182*598139dcSAndroid Build Coastguard Worker * the kernel logging device file, so find and print each line one at
183*598139dcSAndroid Build Coastguard Worker * a time. The allocated size for buf should be at least 1 byte larger
184*598139dcSAndroid Build Coastguard Worker * than buf_size (the usable size of the buffer) to make sure there is
185*598139dcSAndroid Build Coastguard Worker * room to temporarily stuff a null byte to terminate a line for logging.
186*598139dcSAndroid Build Coastguard Worker */
print_buf_lines(struct log_info * log_info,char * buf,int buf_size)187*598139dcSAndroid Build Coastguard Worker static void print_buf_lines(struct log_info* log_info, char* buf, int buf_size) {
188*598139dcSAndroid Build Coastguard Worker char* line_start;
189*598139dcSAndroid Build Coastguard Worker char c;
190*598139dcSAndroid Build Coastguard Worker int i;
191*598139dcSAndroid Build Coastguard Worker
192*598139dcSAndroid Build Coastguard Worker line_start = buf;
193*598139dcSAndroid Build Coastguard Worker for (i = 0; i < buf_size; i++) {
194*598139dcSAndroid Build Coastguard Worker if (*(buf + i) == '\n') {
195*598139dcSAndroid Build Coastguard Worker /* Found a line ending, print the line and compute new line_start */
196*598139dcSAndroid Build Coastguard Worker /* Save the next char and replace with \0 */
197*598139dcSAndroid Build Coastguard Worker c = *(buf + i + 1);
198*598139dcSAndroid Build Coastguard Worker *(buf + i + 1) = '\0';
199*598139dcSAndroid Build Coastguard Worker do_log_line(log_info, line_start);
200*598139dcSAndroid Build Coastguard Worker /* Restore the saved char */
201*598139dcSAndroid Build Coastguard Worker *(buf + i + 1) = c;
202*598139dcSAndroid Build Coastguard Worker line_start = buf + i + 1;
203*598139dcSAndroid Build Coastguard Worker } else if (*(buf + i) == '\0') {
204*598139dcSAndroid Build Coastguard Worker /* The end of the buffer, print the last bit */
205*598139dcSAndroid Build Coastguard Worker do_log_line(log_info, line_start);
206*598139dcSAndroid Build Coastguard Worker break;
207*598139dcSAndroid Build Coastguard Worker }
208*598139dcSAndroid Build Coastguard Worker }
209*598139dcSAndroid Build Coastguard Worker /* If the buffer was completely full, and didn't end with a newline, just
210*598139dcSAndroid Build Coastguard Worker * ignore the partial last line.
211*598139dcSAndroid Build Coastguard Worker */
212*598139dcSAndroid Build Coastguard Worker }
213*598139dcSAndroid Build Coastguard Worker
init_abbr_buf(struct abbr_buf * a_buf)214*598139dcSAndroid Build Coastguard Worker static void init_abbr_buf(struct abbr_buf* a_buf) {
215*598139dcSAndroid Build Coastguard Worker char* new_buf;
216*598139dcSAndroid Build Coastguard Worker
217*598139dcSAndroid Build Coastguard Worker memset(a_buf, 0, sizeof(struct abbr_buf));
218*598139dcSAndroid Build Coastguard Worker new_buf = static_cast<char*>(malloc(BEGINNING_BUF_SIZE));
219*598139dcSAndroid Build Coastguard Worker if (new_buf) {
220*598139dcSAndroid Build Coastguard Worker a_buf->b_buf.buf = new_buf;
221*598139dcSAndroid Build Coastguard Worker a_buf->b_buf.alloc_len = BEGINNING_BUF_SIZE;
222*598139dcSAndroid Build Coastguard Worker a_buf->b_buf.buf_size = BEGINNING_BUF_SIZE - 1;
223*598139dcSAndroid Build Coastguard Worker }
224*598139dcSAndroid Build Coastguard Worker new_buf = static_cast<char*>(malloc(ENDING_BUF_SIZE));
225*598139dcSAndroid Build Coastguard Worker if (new_buf) {
226*598139dcSAndroid Build Coastguard Worker a_buf->e_buf.buf = new_buf;
227*598139dcSAndroid Build Coastguard Worker a_buf->e_buf.alloc_len = ENDING_BUF_SIZE;
228*598139dcSAndroid Build Coastguard Worker a_buf->e_buf.buf_size = ENDING_BUF_SIZE - 1;
229*598139dcSAndroid Build Coastguard Worker }
230*598139dcSAndroid Build Coastguard Worker }
231*598139dcSAndroid Build Coastguard Worker
free_abbr_buf(struct abbr_buf * a_buf)232*598139dcSAndroid Build Coastguard Worker static void free_abbr_buf(struct abbr_buf* a_buf) {
233*598139dcSAndroid Build Coastguard Worker free(a_buf->b_buf.buf);
234*598139dcSAndroid Build Coastguard Worker free(a_buf->e_buf.buf);
235*598139dcSAndroid Build Coastguard Worker }
236*598139dcSAndroid Build Coastguard Worker
add_line_to_abbr_buf(struct abbr_buf * a_buf,char * linebuf,int linelen)237*598139dcSAndroid Build Coastguard Worker static void add_line_to_abbr_buf(struct abbr_buf* a_buf, char* linebuf, int linelen) {
238*598139dcSAndroid Build Coastguard Worker if (!a_buf->beginning_buf_full) {
239*598139dcSAndroid Build Coastguard Worker a_buf->beginning_buf_full = add_line_to_linear_buf(&a_buf->b_buf, linebuf, linelen);
240*598139dcSAndroid Build Coastguard Worker }
241*598139dcSAndroid Build Coastguard Worker if (a_buf->beginning_buf_full) {
242*598139dcSAndroid Build Coastguard Worker add_line_to_circular_buf(&a_buf->e_buf, linebuf, linelen);
243*598139dcSAndroid Build Coastguard Worker }
244*598139dcSAndroid Build Coastguard Worker }
245*598139dcSAndroid Build Coastguard Worker
print_abbr_buf(struct log_info * log_info)246*598139dcSAndroid Build Coastguard Worker static void print_abbr_buf(struct log_info* log_info) {
247*598139dcSAndroid Build Coastguard Worker struct abbr_buf* a_buf = &log_info->a_buf;
248*598139dcSAndroid Build Coastguard Worker
249*598139dcSAndroid Build Coastguard Worker /* Add the abbreviated output to the kernel log */
250*598139dcSAndroid Build Coastguard Worker if (a_buf->b_buf.alloc_len) {
251*598139dcSAndroid Build Coastguard Worker print_buf_lines(log_info, a_buf->b_buf.buf, a_buf->b_buf.used_len);
252*598139dcSAndroid Build Coastguard Worker }
253*598139dcSAndroid Build Coastguard Worker
254*598139dcSAndroid Build Coastguard Worker /* Print an ellipsis to indicate that the buffer has wrapped or
255*598139dcSAndroid Build Coastguard Worker * is full, and some data was not logged.
256*598139dcSAndroid Build Coastguard Worker */
257*598139dcSAndroid Build Coastguard Worker if (a_buf->e_buf.used_len == a_buf->e_buf.buf_size) {
258*598139dcSAndroid Build Coastguard Worker do_log_line(log_info, "...\n");
259*598139dcSAndroid Build Coastguard Worker }
260*598139dcSAndroid Build Coastguard Worker
261*598139dcSAndroid Build Coastguard Worker if (a_buf->e_buf.used_len == 0) {
262*598139dcSAndroid Build Coastguard Worker return;
263*598139dcSAndroid Build Coastguard Worker }
264*598139dcSAndroid Build Coastguard Worker
265*598139dcSAndroid Build Coastguard Worker /* Simplest way to print the circular buffer is allocate a second buf
266*598139dcSAndroid Build Coastguard Worker * of the same size, and memcpy it so it's a simple linear buffer,
267*598139dcSAndroid Build Coastguard Worker * and then cal print_buf_lines on it */
268*598139dcSAndroid Build Coastguard Worker if (a_buf->e_buf.read < a_buf->e_buf.write) {
269*598139dcSAndroid Build Coastguard Worker /* no wrap around, just print it */
270*598139dcSAndroid Build Coastguard Worker print_buf_lines(log_info, a_buf->e_buf.buf + a_buf->e_buf.read, a_buf->e_buf.used_len);
271*598139dcSAndroid Build Coastguard Worker } else {
272*598139dcSAndroid Build Coastguard Worker /* The circular buffer will always have at least 1 byte unused,
273*598139dcSAndroid Build Coastguard Worker * so by allocating alloc_len here we will have at least
274*598139dcSAndroid Build Coastguard Worker * 1 byte of space available as required by print_buf_lines().
275*598139dcSAndroid Build Coastguard Worker */
276*598139dcSAndroid Build Coastguard Worker char* nbuf = static_cast<char*>(malloc(a_buf->e_buf.alloc_len));
277*598139dcSAndroid Build Coastguard Worker if (!nbuf) {
278*598139dcSAndroid Build Coastguard Worker return;
279*598139dcSAndroid Build Coastguard Worker }
280*598139dcSAndroid Build Coastguard Worker int first_chunk_len = a_buf->e_buf.buf_size - a_buf->e_buf.read;
281*598139dcSAndroid Build Coastguard Worker memcpy(nbuf, a_buf->e_buf.buf + a_buf->e_buf.read, first_chunk_len);
282*598139dcSAndroid Build Coastguard Worker /* copy second chunk */
283*598139dcSAndroid Build Coastguard Worker memcpy(nbuf + first_chunk_len, a_buf->e_buf.buf, a_buf->e_buf.write);
284*598139dcSAndroid Build Coastguard Worker print_buf_lines(log_info, nbuf, first_chunk_len + a_buf->e_buf.write);
285*598139dcSAndroid Build Coastguard Worker free(nbuf);
286*598139dcSAndroid Build Coastguard Worker }
287*598139dcSAndroid Build Coastguard Worker }
288*598139dcSAndroid Build Coastguard Worker
289*598139dcSAndroid Build Coastguard Worker static void signal_handler(int signal_num);
290*598139dcSAndroid Build Coastguard Worker
block_signals(sigset_t * oldset)291*598139dcSAndroid Build Coastguard Worker static void block_signals(sigset_t* oldset) {
292*598139dcSAndroid Build Coastguard Worker sigset_t blockset;
293*598139dcSAndroid Build Coastguard Worker
294*598139dcSAndroid Build Coastguard Worker sigemptyset(&blockset);
295*598139dcSAndroid Build Coastguard Worker sigaddset(&blockset, SIGINT);
296*598139dcSAndroid Build Coastguard Worker sigaddset(&blockset, SIGQUIT);
297*598139dcSAndroid Build Coastguard Worker sigaddset(&blockset, SIGHUP);
298*598139dcSAndroid Build Coastguard Worker pthread_sigmask(SIG_BLOCK, &blockset, oldset);
299*598139dcSAndroid Build Coastguard Worker }
300*598139dcSAndroid Build Coastguard Worker
unblock_signals(sigset_t * oldset)301*598139dcSAndroid Build Coastguard Worker static void unblock_signals(sigset_t* oldset) {
302*598139dcSAndroid Build Coastguard Worker pthread_sigmask(SIG_SETMASK, oldset, nullptr);
303*598139dcSAndroid Build Coastguard Worker }
304*598139dcSAndroid Build Coastguard Worker
setup_signal_handlers(pid_t pid)305*598139dcSAndroid Build Coastguard Worker static void setup_signal_handlers(pid_t pid) {
306*598139dcSAndroid Build Coastguard Worker struct sigaction handler = {.sa_handler = signal_handler};
307*598139dcSAndroid Build Coastguard Worker
308*598139dcSAndroid Build Coastguard Worker child_pid = pid;
309*598139dcSAndroid Build Coastguard Worker sigaction(SIGINT, &handler, &old_int);
310*598139dcSAndroid Build Coastguard Worker sigaction(SIGQUIT, &handler, &old_quit);
311*598139dcSAndroid Build Coastguard Worker sigaction(SIGHUP, &handler, &old_hup);
312*598139dcSAndroid Build Coastguard Worker }
313*598139dcSAndroid Build Coastguard Worker
restore_signal_handlers()314*598139dcSAndroid Build Coastguard Worker static void restore_signal_handlers() {
315*598139dcSAndroid Build Coastguard Worker sigaction(SIGINT, &old_int, nullptr);
316*598139dcSAndroid Build Coastguard Worker sigaction(SIGQUIT, &old_quit, nullptr);
317*598139dcSAndroid Build Coastguard Worker sigaction(SIGHUP, &old_hup, nullptr);
318*598139dcSAndroid Build Coastguard Worker child_pid = 0;
319*598139dcSAndroid Build Coastguard Worker }
320*598139dcSAndroid Build Coastguard Worker
signal_handler(int signal_num)321*598139dcSAndroid Build Coastguard Worker static void signal_handler(int signal_num) {
322*598139dcSAndroid Build Coastguard Worker if (child_pid == 0 || kill(child_pid, signal_num) != 0) {
323*598139dcSAndroid Build Coastguard Worker restore_signal_handlers();
324*598139dcSAndroid Build Coastguard Worker raise(signal_num);
325*598139dcSAndroid Build Coastguard Worker }
326*598139dcSAndroid Build Coastguard Worker }
327*598139dcSAndroid Build Coastguard Worker
parent(const char * tag,int parent_read,pid_t pid,int * chld_sts,int log_target,bool abbreviated,const char * file_path,bool forward_signals)328*598139dcSAndroid Build Coastguard Worker static int parent(const char* tag, int parent_read, pid_t pid, int* chld_sts, int log_target,
329*598139dcSAndroid Build Coastguard Worker bool abbreviated, const char* file_path, bool forward_signals) {
330*598139dcSAndroid Build Coastguard Worker int status = 0;
331*598139dcSAndroid Build Coastguard Worker char buffer[4096];
332*598139dcSAndroid Build Coastguard Worker struct pollfd poll_fds[] = {
333*598139dcSAndroid Build Coastguard Worker {
334*598139dcSAndroid Build Coastguard Worker .fd = parent_read,
335*598139dcSAndroid Build Coastguard Worker .events = POLLIN,
336*598139dcSAndroid Build Coastguard Worker },
337*598139dcSAndroid Build Coastguard Worker };
338*598139dcSAndroid Build Coastguard Worker int rc = 0;
339*598139dcSAndroid Build Coastguard Worker int fd;
340*598139dcSAndroid Build Coastguard Worker
341*598139dcSAndroid Build Coastguard Worker struct log_info log_info = {};
342*598139dcSAndroid Build Coastguard Worker
343*598139dcSAndroid Build Coastguard Worker int a = 0; // start index of unprocessed data
344*598139dcSAndroid Build Coastguard Worker int b = 0; // end index of unprocessed data
345*598139dcSAndroid Build Coastguard Worker int sz;
346*598139dcSAndroid Build Coastguard Worker bool found_child = false;
347*598139dcSAndroid Build Coastguard Worker // There is a very small chance that opening child_ptty in the child will fail, but in this case
348*598139dcSAndroid Build Coastguard Worker // POLLHUP will not be generated below. Therefore, we use a 1 second timeout for poll() until
349*598139dcSAndroid Build Coastguard Worker // we receive a message from child_ptty. If this times out, we call waitpid() with WNOHANG to
350*598139dcSAndroid Build Coastguard Worker // check the status of the child process and exit appropriately if it has terminated.
351*598139dcSAndroid Build Coastguard Worker bool received_messages = false;
352*598139dcSAndroid Build Coastguard Worker char tmpbuf[256];
353*598139dcSAndroid Build Coastguard Worker
354*598139dcSAndroid Build Coastguard Worker log_info.btag = basename(tag);
355*598139dcSAndroid Build Coastguard Worker if (!log_info.btag) {
356*598139dcSAndroid Build Coastguard Worker log_info.btag = tag;
357*598139dcSAndroid Build Coastguard Worker }
358*598139dcSAndroid Build Coastguard Worker
359*598139dcSAndroid Build Coastguard Worker if (abbreviated && (log_target == LOG_NONE)) {
360*598139dcSAndroid Build Coastguard Worker abbreviated = 0;
361*598139dcSAndroid Build Coastguard Worker }
362*598139dcSAndroid Build Coastguard Worker if (abbreviated) {
363*598139dcSAndroid Build Coastguard Worker init_abbr_buf(&log_info.a_buf);
364*598139dcSAndroid Build Coastguard Worker }
365*598139dcSAndroid Build Coastguard Worker
366*598139dcSAndroid Build Coastguard Worker if (log_target & LOG_KLOG) {
367*598139dcSAndroid Build Coastguard Worker snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt), "<6>%.*s: %%s\n", MAX_KLOG_TAG,
368*598139dcSAndroid Build Coastguard Worker log_info.btag);
369*598139dcSAndroid Build Coastguard Worker }
370*598139dcSAndroid Build Coastguard Worker
371*598139dcSAndroid Build Coastguard Worker if ((log_target & LOG_FILE) && !file_path) {
372*598139dcSAndroid Build Coastguard Worker /* No file_path specified, clear the LOG_FILE bit */
373*598139dcSAndroid Build Coastguard Worker log_target &= ~LOG_FILE;
374*598139dcSAndroid Build Coastguard Worker }
375*598139dcSAndroid Build Coastguard Worker
376*598139dcSAndroid Build Coastguard Worker if (log_target & LOG_FILE) {
377*598139dcSAndroid Build Coastguard Worker fd = open(file_path, O_WRONLY | O_CREAT | O_CLOEXEC, 0664);
378*598139dcSAndroid Build Coastguard Worker if (fd < 0) {
379*598139dcSAndroid Build Coastguard Worker ERROR("Cannot log to file %s\n", file_path);
380*598139dcSAndroid Build Coastguard Worker log_target &= ~LOG_FILE;
381*598139dcSAndroid Build Coastguard Worker } else {
382*598139dcSAndroid Build Coastguard Worker lseek(fd, 0, SEEK_END);
383*598139dcSAndroid Build Coastguard Worker log_info.fp = fdopen(fd, "a");
384*598139dcSAndroid Build Coastguard Worker }
385*598139dcSAndroid Build Coastguard Worker }
386*598139dcSAndroid Build Coastguard Worker
387*598139dcSAndroid Build Coastguard Worker log_info.log_target = log_target;
388*598139dcSAndroid Build Coastguard Worker log_info.abbreviated = abbreviated;
389*598139dcSAndroid Build Coastguard Worker
390*598139dcSAndroid Build Coastguard Worker while (!found_child) {
391*598139dcSAndroid Build Coastguard Worker int timeout = received_messages ? -1 : 1000;
392*598139dcSAndroid Build Coastguard Worker if (TEMP_FAILURE_RETRY(poll(poll_fds, arraysize(poll_fds), timeout)) < 0) {
393*598139dcSAndroid Build Coastguard Worker ERROR("poll failed\n");
394*598139dcSAndroid Build Coastguard Worker rc = -1;
395*598139dcSAndroid Build Coastguard Worker goto err_poll;
396*598139dcSAndroid Build Coastguard Worker }
397*598139dcSAndroid Build Coastguard Worker
398*598139dcSAndroid Build Coastguard Worker if (poll_fds[0].revents & POLLIN) {
399*598139dcSAndroid Build Coastguard Worker received_messages = true;
400*598139dcSAndroid Build Coastguard Worker sz = TEMP_FAILURE_RETRY(read(parent_read, &buffer[b], sizeof(buffer) - 1 - b));
401*598139dcSAndroid Build Coastguard Worker
402*598139dcSAndroid Build Coastguard Worker sz += b;
403*598139dcSAndroid Build Coastguard Worker // Log one line at a time
404*598139dcSAndroid Build Coastguard Worker for (b = 0; b < sz; b++) {
405*598139dcSAndroid Build Coastguard Worker if (buffer[b] == '\r') {
406*598139dcSAndroid Build Coastguard Worker if (abbreviated) {
407*598139dcSAndroid Build Coastguard Worker /* The abbreviated logging code uses newline as
408*598139dcSAndroid Build Coastguard Worker * the line separator. Lucikly, the pty layer
409*598139dcSAndroid Build Coastguard Worker * helpfully cooks the output of the command
410*598139dcSAndroid Build Coastguard Worker * being run and inserts a CR before NL. So
411*598139dcSAndroid Build Coastguard Worker * I just change it to NL here when doing
412*598139dcSAndroid Build Coastguard Worker * abbreviated logging.
413*598139dcSAndroid Build Coastguard Worker */
414*598139dcSAndroid Build Coastguard Worker buffer[b] = '\n';
415*598139dcSAndroid Build Coastguard Worker } else {
416*598139dcSAndroid Build Coastguard Worker buffer[b] = '\0';
417*598139dcSAndroid Build Coastguard Worker }
418*598139dcSAndroid Build Coastguard Worker } else if (buffer[b] == '\n') {
419*598139dcSAndroid Build Coastguard Worker buffer[b] = '\0';
420*598139dcSAndroid Build Coastguard Worker log_line(&log_info, &buffer[a], b - a);
421*598139dcSAndroid Build Coastguard Worker a = b + 1;
422*598139dcSAndroid Build Coastguard Worker }
423*598139dcSAndroid Build Coastguard Worker }
424*598139dcSAndroid Build Coastguard Worker
425*598139dcSAndroid Build Coastguard Worker if (a == 0 && b == sizeof(buffer) - 1) {
426*598139dcSAndroid Build Coastguard Worker // buffer is full, flush
427*598139dcSAndroid Build Coastguard Worker buffer[b] = '\0';
428*598139dcSAndroid Build Coastguard Worker log_line(&log_info, &buffer[a], b - a);
429*598139dcSAndroid Build Coastguard Worker b = 0;
430*598139dcSAndroid Build Coastguard Worker } else if (a != b) {
431*598139dcSAndroid Build Coastguard Worker // Keep left-overs
432*598139dcSAndroid Build Coastguard Worker b -= a;
433*598139dcSAndroid Build Coastguard Worker memmove(buffer, &buffer[a], b);
434*598139dcSAndroid Build Coastguard Worker a = 0;
435*598139dcSAndroid Build Coastguard Worker } else {
436*598139dcSAndroid Build Coastguard Worker a = 0;
437*598139dcSAndroid Build Coastguard Worker b = 0;
438*598139dcSAndroid Build Coastguard Worker }
439*598139dcSAndroid Build Coastguard Worker }
440*598139dcSAndroid Build Coastguard Worker
441*598139dcSAndroid Build Coastguard Worker if (!received_messages || (poll_fds[0].revents & POLLHUP)) {
442*598139dcSAndroid Build Coastguard Worker int ret;
443*598139dcSAndroid Build Coastguard Worker sigset_t oldset;
444*598139dcSAndroid Build Coastguard Worker
445*598139dcSAndroid Build Coastguard Worker if (forward_signals) {
446*598139dcSAndroid Build Coastguard Worker // Our signal handlers forward these signals to 'child_pid', but waitpid() may reap
447*598139dcSAndroid Build Coastguard Worker // the child, so we must block these signals until we either 1) conclude that the
448*598139dcSAndroid Build Coastguard Worker // child is still running or 2) determine the child has been reaped and we have
449*598139dcSAndroid Build Coastguard Worker // reset the signals to their original disposition.
450*598139dcSAndroid Build Coastguard Worker block_signals(&oldset);
451*598139dcSAndroid Build Coastguard Worker }
452*598139dcSAndroid Build Coastguard Worker
453*598139dcSAndroid Build Coastguard Worker int flags = (poll_fds[0].revents & POLLHUP) ? 0 : WNOHANG;
454*598139dcSAndroid Build Coastguard Worker ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, flags));
455*598139dcSAndroid Build Coastguard Worker if (ret < 0) {
456*598139dcSAndroid Build Coastguard Worker rc = errno;
457*598139dcSAndroid Build Coastguard Worker ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));
458*598139dcSAndroid Build Coastguard Worker goto err_waitpid;
459*598139dcSAndroid Build Coastguard Worker }
460*598139dcSAndroid Build Coastguard Worker if (ret > 0) {
461*598139dcSAndroid Build Coastguard Worker found_child = true;
462*598139dcSAndroid Build Coastguard Worker }
463*598139dcSAndroid Build Coastguard Worker
464*598139dcSAndroid Build Coastguard Worker if (forward_signals) {
465*598139dcSAndroid Build Coastguard Worker if (found_child) {
466*598139dcSAndroid Build Coastguard Worker restore_signal_handlers();
467*598139dcSAndroid Build Coastguard Worker }
468*598139dcSAndroid Build Coastguard Worker unblock_signals(&oldset);
469*598139dcSAndroid Build Coastguard Worker }
470*598139dcSAndroid Build Coastguard Worker }
471*598139dcSAndroid Build Coastguard Worker }
472*598139dcSAndroid Build Coastguard Worker
473*598139dcSAndroid Build Coastguard Worker if (chld_sts != nullptr) {
474*598139dcSAndroid Build Coastguard Worker *chld_sts = status;
475*598139dcSAndroid Build Coastguard Worker } else {
476*598139dcSAndroid Build Coastguard Worker if (WIFEXITED(status))
477*598139dcSAndroid Build Coastguard Worker rc = WEXITSTATUS(status);
478*598139dcSAndroid Build Coastguard Worker else
479*598139dcSAndroid Build Coastguard Worker rc = -ECHILD;
480*598139dcSAndroid Build Coastguard Worker }
481*598139dcSAndroid Build Coastguard Worker
482*598139dcSAndroid Build Coastguard Worker // Flush remaining data
483*598139dcSAndroid Build Coastguard Worker if (a != b) {
484*598139dcSAndroid Build Coastguard Worker buffer[b] = '\0';
485*598139dcSAndroid Build Coastguard Worker log_line(&log_info, &buffer[a], b - a);
486*598139dcSAndroid Build Coastguard Worker }
487*598139dcSAndroid Build Coastguard Worker
488*598139dcSAndroid Build Coastguard Worker /* All the output has been processed, time to dump the abbreviated output */
489*598139dcSAndroid Build Coastguard Worker if (abbreviated) {
490*598139dcSAndroid Build Coastguard Worker print_abbr_buf(&log_info);
491*598139dcSAndroid Build Coastguard Worker }
492*598139dcSAndroid Build Coastguard Worker
493*598139dcSAndroid Build Coastguard Worker if (WIFEXITED(status)) {
494*598139dcSAndroid Build Coastguard Worker if (WEXITSTATUS(status)) {
495*598139dcSAndroid Build Coastguard Worker snprintf(tmpbuf, sizeof(tmpbuf), "%s terminated by exit(%d)\n", log_info.btag,
496*598139dcSAndroid Build Coastguard Worker WEXITSTATUS(status));
497*598139dcSAndroid Build Coastguard Worker do_log_line(&log_info, tmpbuf);
498*598139dcSAndroid Build Coastguard Worker }
499*598139dcSAndroid Build Coastguard Worker } else {
500*598139dcSAndroid Build Coastguard Worker if (WIFSIGNALED(status)) {
501*598139dcSAndroid Build Coastguard Worker snprintf(tmpbuf, sizeof(tmpbuf), "%s terminated by signal %d\n", log_info.btag,
502*598139dcSAndroid Build Coastguard Worker WTERMSIG(status));
503*598139dcSAndroid Build Coastguard Worker do_log_line(&log_info, tmpbuf);
504*598139dcSAndroid Build Coastguard Worker } else if (WIFSTOPPED(status)) {
505*598139dcSAndroid Build Coastguard Worker snprintf(tmpbuf, sizeof(tmpbuf), "%s stopped by signal %d\n", log_info.btag,
506*598139dcSAndroid Build Coastguard Worker WSTOPSIG(status));
507*598139dcSAndroid Build Coastguard Worker do_log_line(&log_info, tmpbuf);
508*598139dcSAndroid Build Coastguard Worker }
509*598139dcSAndroid Build Coastguard Worker }
510*598139dcSAndroid Build Coastguard Worker
511*598139dcSAndroid Build Coastguard Worker err_waitpid:
512*598139dcSAndroid Build Coastguard Worker err_poll:
513*598139dcSAndroid Build Coastguard Worker if (log_info.fp) {
514*598139dcSAndroid Build Coastguard Worker fclose(log_info.fp);
515*598139dcSAndroid Build Coastguard Worker }
516*598139dcSAndroid Build Coastguard Worker if (abbreviated) {
517*598139dcSAndroid Build Coastguard Worker free_abbr_buf(&log_info.a_buf);
518*598139dcSAndroid Build Coastguard Worker }
519*598139dcSAndroid Build Coastguard Worker return rc;
520*598139dcSAndroid Build Coastguard Worker }
521*598139dcSAndroid Build Coastguard Worker
child(int argc,const char * const * argv)522*598139dcSAndroid Build Coastguard Worker static void child(int argc, const char* const* argv) {
523*598139dcSAndroid Build Coastguard Worker // create null terminated argv_child array
524*598139dcSAndroid Build Coastguard Worker char* argv_child[argc + 1];
525*598139dcSAndroid Build Coastguard Worker memcpy(argv_child, argv, argc * sizeof(char*));
526*598139dcSAndroid Build Coastguard Worker argv_child[argc] = nullptr;
527*598139dcSAndroid Build Coastguard Worker
528*598139dcSAndroid Build Coastguard Worker if (execvp(argv_child[0], argv_child)) {
529*598139dcSAndroid Build Coastguard Worker FATAL_CHILD("executing %s failed: %s\n", argv_child[0], strerror(errno));
530*598139dcSAndroid Build Coastguard Worker }
531*598139dcSAndroid Build Coastguard Worker }
532*598139dcSAndroid Build Coastguard Worker
logwrap_fork_execvp(int argc,const char * const * argv,int * status,bool forward_signals,int log_target,bool abbreviated,const char * file_path)533*598139dcSAndroid Build Coastguard Worker int logwrap_fork_execvp(int argc, const char* const* argv, int* status, bool forward_signals,
534*598139dcSAndroid Build Coastguard Worker int log_target, bool abbreviated, const char* file_path) {
535*598139dcSAndroid Build Coastguard Worker pid_t pid;
536*598139dcSAndroid Build Coastguard Worker int parent_ptty;
537*598139dcSAndroid Build Coastguard Worker sigset_t oldset;
538*598139dcSAndroid Build Coastguard Worker int rc = 0;
539*598139dcSAndroid Build Coastguard Worker
540*598139dcSAndroid Build Coastguard Worker rc = pthread_mutex_lock(&fd_mutex);
541*598139dcSAndroid Build Coastguard Worker if (rc) {
542*598139dcSAndroid Build Coastguard Worker ERROR("failed to lock signal_fd mutex\n");
543*598139dcSAndroid Build Coastguard Worker goto err_lock;
544*598139dcSAndroid Build Coastguard Worker }
545*598139dcSAndroid Build Coastguard Worker
546*598139dcSAndroid Build Coastguard Worker /* Use ptty instead of socketpair so that STDOUT is not buffered */
547*598139dcSAndroid Build Coastguard Worker parent_ptty = TEMP_FAILURE_RETRY(posix_openpt(O_RDWR | O_CLOEXEC));
548*598139dcSAndroid Build Coastguard Worker if (parent_ptty < 0) {
549*598139dcSAndroid Build Coastguard Worker ERROR("Cannot create parent ptty\n");
550*598139dcSAndroid Build Coastguard Worker rc = -1;
551*598139dcSAndroid Build Coastguard Worker goto err_open;
552*598139dcSAndroid Build Coastguard Worker }
553*598139dcSAndroid Build Coastguard Worker
554*598139dcSAndroid Build Coastguard Worker char child_devname[64];
555*598139dcSAndroid Build Coastguard Worker if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
556*598139dcSAndroid Build Coastguard Worker ptsname_r(parent_ptty, child_devname, sizeof(child_devname)) != 0) {
557*598139dcSAndroid Build Coastguard Worker ERROR("Problem with /dev/ptmx\n");
558*598139dcSAndroid Build Coastguard Worker rc = -1;
559*598139dcSAndroid Build Coastguard Worker goto err_ptty;
560*598139dcSAndroid Build Coastguard Worker }
561*598139dcSAndroid Build Coastguard Worker
562*598139dcSAndroid Build Coastguard Worker if (forward_signals) {
563*598139dcSAndroid Build Coastguard Worker // Block these signals until we have the child pid and our signal handlers set up.
564*598139dcSAndroid Build Coastguard Worker block_signals(&oldset);
565*598139dcSAndroid Build Coastguard Worker }
566*598139dcSAndroid Build Coastguard Worker
567*598139dcSAndroid Build Coastguard Worker pid = fork();
568*598139dcSAndroid Build Coastguard Worker if (pid < 0) {
569*598139dcSAndroid Build Coastguard Worker ERROR("Failed to fork\n");
570*598139dcSAndroid Build Coastguard Worker rc = -1;
571*598139dcSAndroid Build Coastguard Worker goto err_fork;
572*598139dcSAndroid Build Coastguard Worker } else if (pid == 0) {
573*598139dcSAndroid Build Coastguard Worker pthread_mutex_unlock(&fd_mutex);
574*598139dcSAndroid Build Coastguard Worker if (forward_signals) {
575*598139dcSAndroid Build Coastguard Worker unblock_signals(&oldset);
576*598139dcSAndroid Build Coastguard Worker }
577*598139dcSAndroid Build Coastguard Worker
578*598139dcSAndroid Build Coastguard Worker setsid();
579*598139dcSAndroid Build Coastguard Worker
580*598139dcSAndroid Build Coastguard Worker int child_ptty = TEMP_FAILURE_RETRY(open(child_devname, O_RDWR | O_CLOEXEC));
581*598139dcSAndroid Build Coastguard Worker if (child_ptty < 0) {
582*598139dcSAndroid Build Coastguard Worker FATAL_CHILD("Cannot open child_ptty: %s\n", strerror(errno));
583*598139dcSAndroid Build Coastguard Worker }
584*598139dcSAndroid Build Coastguard Worker close(parent_ptty);
585*598139dcSAndroid Build Coastguard Worker
586*598139dcSAndroid Build Coastguard Worker dup2(child_ptty, 1);
587*598139dcSAndroid Build Coastguard Worker dup2(child_ptty, 2);
588*598139dcSAndroid Build Coastguard Worker close(child_ptty);
589*598139dcSAndroid Build Coastguard Worker
590*598139dcSAndroid Build Coastguard Worker child(argc, argv);
591*598139dcSAndroid Build Coastguard Worker } else {
592*598139dcSAndroid Build Coastguard Worker if (forward_signals) {
593*598139dcSAndroid Build Coastguard Worker setup_signal_handlers(pid);
594*598139dcSAndroid Build Coastguard Worker unblock_signals(&oldset);
595*598139dcSAndroid Build Coastguard Worker }
596*598139dcSAndroid Build Coastguard Worker
597*598139dcSAndroid Build Coastguard Worker rc = parent(argv[0], parent_ptty, pid, status, log_target, abbreviated, file_path,
598*598139dcSAndroid Build Coastguard Worker forward_signals);
599*598139dcSAndroid Build Coastguard Worker
600*598139dcSAndroid Build Coastguard Worker if (forward_signals) {
601*598139dcSAndroid Build Coastguard Worker restore_signal_handlers();
602*598139dcSAndroid Build Coastguard Worker }
603*598139dcSAndroid Build Coastguard Worker }
604*598139dcSAndroid Build Coastguard Worker
605*598139dcSAndroid Build Coastguard Worker err_fork:
606*598139dcSAndroid Build Coastguard Worker if (forward_signals) {
607*598139dcSAndroid Build Coastguard Worker unblock_signals(&oldset);
608*598139dcSAndroid Build Coastguard Worker }
609*598139dcSAndroid Build Coastguard Worker err_ptty:
610*598139dcSAndroid Build Coastguard Worker close(parent_ptty);
611*598139dcSAndroid Build Coastguard Worker err_open:
612*598139dcSAndroid Build Coastguard Worker pthread_mutex_unlock(&fd_mutex);
613*598139dcSAndroid Build Coastguard Worker err_lock:
614*598139dcSAndroid Build Coastguard Worker return rc;
615*598139dcSAndroid Build Coastguard Worker }
616