Cleanup: initialize data to 0
[lttng-tools.git] / src / common / runas.c
CommitLineData
60b6c79c
MD
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 *
d14d33bf
AM
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2 only,
7 * as published by the Free Software Foundation.
60b6c79c
MD
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
d14d33bf 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
60b6c79c
MD
12 * more details.
13 *
d14d33bf
AM
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
60b6c79c
MD
17 */
18
6c1c0768 19#define _LGPL_SOURCE
60b6c79c
MD
20#include <errno.h>
21#include <limits.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/wait.h>
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <unistd.h>
29#include <fcntl.h>
c2b75c49 30#include <sched.h>
0452bf08 31#include <signal.h>
749b7a0c 32#include <assert.h>
e1055edb 33#include <signal.h>
60b6c79c 34
90e535ef 35#include <common/common.h>
3fd15a74 36#include <common/utils.h>
e8fa9fb0 37#include <common/compat/getenv.h>
e1055edb 38#include <common/compat/prctl.h>
2038dd6c
JG
39#include <common/unix.h>
40#include <common/defaults.h>
60b6c79c 41
0857097f
DG
42#include "runas.h"
43
7567352f
MD
44struct run_as_data;
45typedef int (*run_as_fct)(struct run_as_data *data);
c2b75c49 46
e11d277b 47struct run_as_mkdir_data {
7567352f 48 char path[PATH_MAX];
60b6c79c
MD
49 mode_t mode;
50};
51
e11d277b 52struct run_as_open_data {
7567352f 53 char path[PATH_MAX];
60b6c79c
MD
54 int flags;
55 mode_t mode;
56};
57
4628484a 58struct run_as_unlink_data {
7567352f 59 char path[PATH_MAX];
4628484a
MD
60};
61
7567352f
MD
62struct run_as_rmdir_recursive_data {
63 char path[PATH_MAX];
64};
65
66enum run_as_cmd {
67 RUN_AS_MKDIR,
68 RUN_AS_OPEN,
69 RUN_AS_UNLINK,
70 RUN_AS_RMDIR_RECURSIVE,
71 RUN_AS_MKDIR_RECURSIVE,
72};
73
74struct run_as_data {
75 enum run_as_cmd cmd;
76 union {
77 struct run_as_mkdir_data mkdir;
78 struct run_as_open_data open;
79 struct run_as_unlink_data unlink;
80 struct run_as_rmdir_recursive_data rmdir_recursive;
81 } u;
82 uid_t uid;
83 gid_t gid;
4628484a
MD
84};
85
df5b86c8
MD
86struct run_as_ret {
87 int ret;
88 int _errno;
89};
90
7567352f
MD
91struct run_as_worker {
92 pid_t pid; /* Worker PID. */
93 int sockpair[2];
94 char *procname;
95};
96
97/* Single global worker per process (for now). */
98static struct run_as_worker *global_worker;
99/* Lock protecting the worker. */
100static pthread_mutex_t worker_lock = PTHREAD_MUTEX_INITIALIZER;
101
8f0044bf
MD
102#ifdef VALGRIND
103static
104int use_clone(void)
105{
106 return 0;
107}
108#else
109static
110int use_clone(void)
111{
e8fa9fb0 112 return !lttng_secure_getenv("LTTNG_DEBUG_NOCLONE");
8f0044bf
MD
113}
114#endif
115
d77dded2
JG
116LTTNG_HIDDEN
117int _utils_mkdir_recursive_unsafe(const char *path, mode_t mode);
118
60b6c79c
MD
119/*
120 * Create recursively directory using the FULL path.
121 */
122static
7567352f 123int _mkdir_recursive(struct run_as_data *data)
60b6c79c 124{
60b6c79c 125 const char *path;
60b6c79c 126 mode_t mode;
60b6c79c 127
7567352f
MD
128 path = data->u.mkdir.path;
129 mode = data->u.mkdir.mode;
60b6c79c 130
d77dded2
JG
131 /* Safe to call as we have transitioned to the requested uid/gid. */
132 return _utils_mkdir_recursive_unsafe(path, mode);
60b6c79c
MD
133}
134
135static
7567352f 136int _mkdir(struct run_as_data *data)
60b6c79c 137{
7567352f
MD
138 return mkdir(data->u.mkdir.path, data->u.mkdir.mode);
139}
7ce36756 140
7567352f
MD
141static
142int _open(struct run_as_data *data)
143{
144 return open(data->u.open.path, data->u.open.flags, data->u.open.mode);
145}
146
147static
148int _unlink(struct run_as_data *data)
149{
150 return unlink(data->u.unlink.path);
60b6c79c
MD
151}
152
153static
7567352f 154int _rmdir_recursive(struct run_as_data *data)
60b6c79c 155{
7567352f
MD
156 return utils_recursive_rmdir(data->u.rmdir_recursive.path);
157}
df5b86c8 158
7567352f
MD
159static
160run_as_fct run_as_enum_to_fct(enum run_as_cmd cmd)
161{
162 switch (cmd) {
163 case RUN_AS_MKDIR:
164 return _mkdir;
165 case RUN_AS_OPEN:
166 return _open;
167 case RUN_AS_UNLINK:
168 return _unlink;
169 case RUN_AS_RMDIR_RECURSIVE:
170 return _rmdir_recursive;
171 case RUN_AS_MKDIR_RECURSIVE:
172 return _mkdir_recursive;
173 default:
62a7b8ed 174 ERR("Unknown command %d", (int) cmd);
7567352f
MD
175 return NULL;
176 }
60b6c79c
MD
177}
178
4628484a 179static
7567352f
MD
180int do_send_fd(struct run_as_worker *worker,
181 enum run_as_cmd cmd, int fd)
4628484a 182{
7567352f 183 ssize_t len;
4628484a 184
7567352f
MD
185 switch (cmd) {
186 case RUN_AS_OPEN:
187 break;
188 default:
189 return 0;
190 }
191 if (fd < 0) {
192 return 0;
193 }
194 len = lttcomm_send_fds_unix_sock(worker->sockpair[1], &fd, 1);
195 if (len < 0) {
196 PERROR("lttcomm_send_fds_unix_sock");
197 return -1;
198 }
199 if (close(fd) < 0) {
200 PERROR("close");
201 return -1;
202 }
203 return 0;
4628484a
MD
204}
205
206static
7567352f
MD
207int do_recv_fd(struct run_as_worker *worker,
208 enum run_as_cmd cmd, int *fd)
4628484a 209{
7567352f 210 ssize_t len;
4628484a 211
7567352f
MD
212 switch (cmd) {
213 case RUN_AS_OPEN:
214 break;
215 default:
216 return 0;
217 }
218 if (*fd < 0) {
219 return 0;
220 }
221 len = lttcomm_recv_fds_unix_sock(worker->sockpair[0], fd, 1);
da9ee832
JG
222 if (!len) {
223 return -1;
224 } else if (len < 0) {
7567352f
MD
225 PERROR("lttcomm_recv_fds_unix_sock");
226 return -1;
227 }
228 return 0;
4628484a
MD
229}
230
7567352f
MD
231/*
232 * Return < 0 on error, 0 if OK, 1 on hangup.
233 */
c2b75c49 234static
7567352f 235int handle_one_cmd(struct run_as_worker *worker)
c2b75c49 236{
7567352f
MD
237 int ret = 0;
238 struct run_as_data data;
239 ssize_t readlen, writelen;
df5b86c8 240 struct run_as_ret sendret;
7567352f
MD
241 run_as_fct cmd;
242 uid_t prev_euid;
243
244 /* Read data */
245 readlen = lttcomm_recv_unix_sock(worker->sockpair[1], &data,
246 sizeof(data));
247 if (readlen == 0) {
248 /* hang up */
249 ret = 1;
250 goto end;
251 }
252 if (readlen < sizeof(data)) {
253 PERROR("lttcomm_recv_unix_sock error");
254 ret = -1;
255 goto end;
256 }
c2b75c49 257
7567352f
MD
258 cmd = run_as_enum_to_fct(data.cmd);
259 if (!cmd) {
260 ret = -1;
261 goto end;
262 }
263
264 prev_euid = getuid();
265 if (data.gid != getegid()) {
266 ret = setegid(data.gid);
1576d582 267 if (ret < 0) {
4c462e79 268 PERROR("setegid");
6d73c4ef 269 goto write_return;
1576d582 270 }
c2b75c49 271 }
7567352f
MD
272 if (data.uid != prev_euid) {
273 ret = seteuid(data.uid);
1576d582 274 if (ret < 0) {
4c462e79 275 PERROR("seteuid");
6d73c4ef 276 goto write_return;
1576d582 277 }
c2b75c49
MD
278 }
279 /*
280 * Also set umask to 0 for mkdir executable bit.
281 */
282 umask(0);
7567352f 283 ret = (*cmd)(&data);
6d73c4ef
MD
284
285write_return:
df5b86c8
MD
286 sendret.ret = ret;
287 sendret._errno = errno;
c2b75c49 288 /* send back return value */
7567352f
MD
289 writelen = lttcomm_send_unix_sock(worker->sockpair[1], &sendret,
290 sizeof(sendret));
6cd525e8 291 if (writelen < sizeof(sendret)) {
7567352f
MD
292 PERROR("lttcomm_send_unix_sock error");
293 ret = -1;
294 goto end;
295 }
296 ret = do_send_fd(worker, data.cmd, ret);
297 if (ret) {
298 PERROR("do_send_fd error");
299 ret = -1;
300 goto end;
301 }
302 if (seteuid(prev_euid) < 0) {
303 PERROR("seteuid");
304 ret = -1;
305 goto end;
306 }
307 ret = 0;
308end:
309 return ret;
310}
311
312static
313int run_as_worker(struct run_as_worker *worker)
314{
315 int ret;
316 ssize_t writelen;
317 struct run_as_ret sendret;
318 size_t proc_orig_len;
319
320 /*
321 * Initialize worker. Set a different process cmdline.
322 */
323 proc_orig_len = strlen(worker->procname);
324 memset(worker->procname, 0, proc_orig_len);
325 strncpy(worker->procname, DEFAULT_RUN_AS_WORKER_NAME, proc_orig_len);
326
e1055edb
JG
327 ret = lttng_prctl(PR_SET_NAME,
328 (unsigned long) DEFAULT_RUN_AS_WORKER_NAME, 0, 0, 0);
329 if (ret && ret != -ENOSYS) {
b8090274
JG
330 /* Don't fail as this is not essential. */
331 PERROR("prctl PR_SET_NAME");
332 ret = 0;
6cd525e8 333 }
7567352f
MD
334
335 sendret.ret = 0;
336 sendret._errno = 0;
337 writelen = lttcomm_send_unix_sock(worker->sockpair[1], &sendret,
338 sizeof(sendret));
339 if (writelen < sizeof(sendret)) {
340 PERROR("lttcomm_send_unix_sock error");
341 ret = EXIT_FAILURE;
342 goto end;
343 }
344
345 for (;;) {
346 ret = handle_one_cmd(worker);
347 if (ret < 0) {
348 ret = EXIT_FAILURE;
349 goto end;
350 } else if (ret > 0) {
351 break;
352 } else {
353 continue; /* Next command. */
354 }
355 }
356 ret = EXIT_SUCCESS;
357end:
358 return ret;
c2b75c49
MD
359}
360
60b6c79c 361static
7567352f
MD
362int run_as_cmd(struct run_as_worker *worker,
363 enum run_as_cmd cmd,
364 struct run_as_data *data,
365 uid_t uid, gid_t gid)
60b6c79c 366{
7567352f 367 ssize_t readlen, writelen;
df5b86c8 368 struct run_as_ret recvret;
60b6c79c
MD
369
370 /*
371 * If we are non-root, we can only deal with our own uid.
372 */
373 if (geteuid() != 0) {
374 if (uid != geteuid()) {
df5b86c8
MD
375 recvret.ret = -1;
376 recvret._errno = EPERM;
60b6c79c 377 ERR("Client (%d)/Server (%d) UID mismatch (and sessiond is not root)",
08797918 378 (int) uid, (int) geteuid());
df5b86c8 379 goto end;
60b6c79c 380 }
60b6c79c
MD
381 }
382
7567352f
MD
383 data->cmd = cmd;
384 data->uid = uid;
385 data->gid = gid;
386
387 writelen = lttcomm_send_unix_sock(worker->sockpair[0], data,
388 sizeof(*data));
389 if (writelen < sizeof(*data)) {
390 PERROR("Error writing message to run_as");
df5b86c8
MD
391 recvret.ret = -1;
392 recvret._errno = errno;
60b6c79c 393 goto end;
c2b75c49 394 }
7567352f 395
c2b75c49 396 /* receive return value */
7567352f
MD
397 readlen = lttcomm_recv_unix_sock(worker->sockpair[0], &recvret,
398 sizeof(recvret));
da9ee832
JG
399 if (!readlen) {
400 ERR("Run-as worker has hung-up during run_as_cmd");
401 recvret.ret = -1;
402 recvret._errno = EIO;
403 goto end;
404 } else if (readlen < sizeof(recvret)) {
7567352f 405 PERROR("Error reading response from run_as");
df5b86c8
MD
406 recvret.ret = -1;
407 recvret._errno = errno;
6cd525e8 408 }
7567352f 409 if (do_recv_fd(worker, cmd, &recvret.ret)) {
df5b86c8 410 recvret.ret = -1;
da9ee832 411 recvret._errno = EIO;
4c462e79 412 }
7567352f 413
60b6c79c 414end:
df5b86c8
MD
415 errno = recvret._errno;
416 return recvret.ret;
60b6c79c
MD
417}
418
2d85a600 419/*
7567352f 420 * This is for debugging ONLY and should not be considered secure.
2d85a600
MD
421 */
422static
7567352f
MD
423int run_as_noworker(enum run_as_cmd cmd,
424 struct run_as_data *data, uid_t uid, gid_t gid)
2d85a600 425{
df5b86c8 426 int ret, saved_errno;
5b73926f 427 mode_t old_mask;
7567352f 428 run_as_fct fct;
5b73926f 429
7567352f
MD
430 fct = run_as_enum_to_fct(cmd);
431 if (!fct) {
432 errno = -ENOSYS;
433 ret = -1;
434 goto end;
435 }
5b73926f 436 old_mask = umask(0);
7567352f 437 ret = fct(data);
df5b86c8 438 saved_errno = errno;
5b73926f 439 umask(old_mask);
df5b86c8 440 errno = saved_errno;
7567352f 441end:
5b73926f 442 return ret;
2d85a600
MD
443}
444
445static
749b7a0c 446int run_as(enum run_as_cmd cmd, struct run_as_data *data, uid_t uid, gid_t gid)
2d85a600 447{
7567352f
MD
448 int ret;
449
749b7a0c 450 if (use_clone()) {
7567352f 451 DBG("Using run_as worker");
749b7a0c
JG
452 pthread_mutex_lock(&worker_lock);
453 assert(global_worker);
454 ret = run_as_cmd(global_worker, cmd, data, uid, gid);
455 pthread_mutex_unlock(&worker_lock);
456
2d85a600 457 } else {
7567352f
MD
458 DBG("Using run_as without worker");
459 ret = run_as_noworker(cmd, data, uid, gid);
2d85a600 460 }
7567352f 461 return ret;
2d85a600
MD
462}
463
90e535ef 464LTTNG_HIDDEN
e11d277b 465int run_as_mkdir_recursive(const char *path, mode_t mode, uid_t uid, gid_t gid)
60b6c79c 466{
7567352f 467 struct run_as_data data;
60b6c79c 468
3914163a 469 memset(&data, 0, sizeof(data));
60b6c79c 470 DBG3("mkdir() recursive %s with mode %d for uid %d and gid %d",
08797918 471 path, (int) mode, (int) uid, (int) gid);
7567352f
MD
472 strncpy(data.u.mkdir.path, path, PATH_MAX - 1);
473 data.u.mkdir.path[PATH_MAX - 1] = '\0';
474 data.u.mkdir.mode = mode;
749b7a0c 475 return run_as(RUN_AS_MKDIR_RECURSIVE, &data, uid, gid);
60b6c79c
MD
476}
477
90e535ef 478LTTNG_HIDDEN
e11d277b 479int run_as_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid)
60b6c79c 480{
7567352f 481 struct run_as_data data;
60b6c79c 482
3914163a 483 memset(&data, 0, sizeof(data));
60b6c79c 484 DBG3("mkdir() %s with mode %d for uid %d and gid %d",
08797918 485 path, (int) mode, (int) uid, (int) gid);
7567352f
MD
486 strncpy(data.u.mkdir.path, path, PATH_MAX - 1);
487 data.u.mkdir.path[PATH_MAX - 1] = '\0';
488 data.u.mkdir.mode = mode;
749b7a0c 489 return run_as(RUN_AS_MKDIR, &data, uid, gid);
60b6c79c
MD
490}
491
492/*
493 * Note: open_run_as is currently not working. We'd need to pass the fd
494 * opened in the child to the parent.
495 */
90e535ef 496LTTNG_HIDDEN
e11d277b 497int run_as_open(const char *path, int flags, mode_t mode, uid_t uid, gid_t gid)
60b6c79c 498{
7567352f 499 struct run_as_data data;
c2b75c49 500
3914163a 501 memset(&data, 0, sizeof(data));
47fb7563 502 DBG3("open() %s with flags %X mode %d for uid %d and gid %d",
08797918 503 path, flags, (int) mode, (int) uid, (int) gid);
7567352f
MD
504 strncpy(data.u.open.path, path, PATH_MAX - 1);
505 data.u.open.path[PATH_MAX - 1] = '\0';
506 data.u.open.flags = flags;
507 data.u.open.mode = mode;
749b7a0c 508 return run_as(RUN_AS_OPEN, &data, uid, gid);
60b6c79c 509}
4628484a
MD
510
511LTTNG_HIDDEN
512int run_as_unlink(const char *path, uid_t uid, gid_t gid)
513{
7567352f 514 struct run_as_data data;
4628484a 515
3914163a 516 memset(&data, 0, sizeof(data));
4628484a 517 DBG3("unlink() %s with for uid %d and gid %d",
08797918 518 path, (int) uid, (int) gid);
7567352f
MD
519 strncpy(data.u.unlink.path, path, PATH_MAX - 1);
520 data.u.unlink.path[PATH_MAX - 1] = '\0';
749b7a0c 521 return run_as(RUN_AS_UNLINK, &data, uid, gid);
4628484a
MD
522}
523
524LTTNG_HIDDEN
7567352f 525int run_as_rmdir_recursive(const char *path, uid_t uid, gid_t gid)
4628484a 526{
7567352f 527 struct run_as_data data;
4628484a 528
7567352f 529 DBG3("rmdir_recursive() %s with for uid %d and gid %d",
08797918 530 path, (int) uid, (int) gid);
7567352f
MD
531 strncpy(data.u.rmdir_recursive.path, path, PATH_MAX - 1);
532 data.u.rmdir_recursive.path[PATH_MAX - 1] = '\0';
749b7a0c 533 return run_as(RUN_AS_RMDIR_RECURSIVE, &data, uid, gid);
7567352f
MD
534}
535
f8f66d38 536static
a80ed305 537int reset_sighandler(void)
f8f66d38 538{
5b5bb8c8 539 int sig;
f8f66d38 540
978d5d79 541 DBG("Resetting run_as worker signal handlers to default");
5b5bb8c8
JG
542 for (sig = 1; sig <= 31; sig++) {
543 (void) signal(sig, SIG_DFL);
f8f66d38 544 }
5b5bb8c8 545 return 0;
a80ed305
JG
546}
547
548static
549void worker_sighandler(int sig)
550{
551 const char *signame;
552
553 /*
cd89f030
JG
554 * The worker will inherit its parent's signals since they are part of
555 * the same process group. However, in the case of SIGINT and SIGTERM,
556 * we want to give the worker a chance to teardown gracefully when its
557 * parent closes the command socket.
a80ed305
JG
558 */
559 switch (sig) {
560 case SIGINT:
561 signame = "SIGINT";
562 break;
563 case SIGTERM:
564 signame = "SIGTERM";
565 break;
566 default:
22d5e48e 567 signame = NULL;
a80ed305
JG
568 }
569
22d5e48e
JG
570 if (signame) {
571 DBG("run_as worker received signal %s", signame);
572 } else {
573 DBG("run_as_worker received signal %d", sig);
574 }
a80ed305
JG
575}
576
577static
578int set_worker_sighandlers(void)
579{
580 int ret = 0;
581 sigset_t sigset;
582 struct sigaction sa;
583
584 if ((ret = sigemptyset(&sigset)) < 0) {
585 PERROR("sigemptyset");
586 goto end;
587 }
588
589 sa.sa_handler = worker_sighandler;
590 sa.sa_mask = sigset;
591 sa.sa_flags = 0;
592 if ((ret = sigaction(SIGINT, &sa, NULL)) < 0) {
593 PERROR("sigaction SIGINT");
594 goto end;
595 }
596
597 if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) {
598 PERROR("sigaction SIGTERM");
599 goto end;
600 }
601
602 DBG("run_as signal handler set for SIGTERM and SIGINT");
603end:
604 return ret;
f8f66d38
JG
605}
606
7567352f
MD
607LTTNG_HIDDEN
608int run_as_create_worker(char *procname)
609{
610 pid_t pid;
611 int i, ret = 0;
612 ssize_t readlen;
613 struct run_as_ret recvret;
614 struct run_as_worker *worker;
615
749b7a0c
JG
616 pthread_mutex_lock(&worker_lock);
617 assert(!global_worker);
7567352f 618 if (!use_clone()) {
749b7a0c
JG
619 /*
620 * Don't initialize a worker, all run_as tasks will be performed
621 * in the current process.
622 */
7567352f
MD
623 ret = 0;
624 goto end;
625 }
626 worker = zmalloc(sizeof(*worker));
627 if (!worker) {
628 ret = -ENOMEM;
629 goto end;
630 }
631 worker->procname = procname;
632 /* Create unix socket. */
633 if (lttcomm_create_anon_unix_socketpair(worker->sockpair) < 0) {
634 ret = -1;
635 goto error_sock;
636 }
637 /* Fork worker. */
638 pid = fork();
639 if (pid < 0) {
640 PERROR("fork");
641 ret = -1;
642 goto error_fork;
643 } else if (pid == 0) {
644 /* Child */
645
f8f66d38
JG
646 reset_sighandler();
647
a80ed305
JG
648 set_worker_sighandlers();
649
749b7a0c
JG
650 /* The child has no use for this lock. */
651 pthread_mutex_unlock(&worker_lock);
7567352f
MD
652 /* Just close, no shutdown. */
653 if (close(worker->sockpair[0])) {
654 PERROR("close");
655 exit(EXIT_FAILURE);
656 }
657 worker->sockpair[0] = -1;
658 ret = run_as_worker(worker);
659 if (lttcomm_close_unix_sock(worker->sockpair[1])) {
660 PERROR("close");
661 ret = -1;
662 }
663 worker->sockpair[1] = -1;
978d5d79 664 LOG(ret ? PRINT_ERR : PRINT_DBG, "run_as worker exiting (ret = %d)", ret);
7567352f
MD
665 exit(ret ? EXIT_FAILURE : EXIT_SUCCESS);
666 } else {
667 /* Parent */
668
669 /* Just close, no shutdown. */
670 if (close(worker->sockpair[1])) {
671 PERROR("close");
672 ret = -1;
673 goto error_fork;
674 }
675 worker->sockpair[1] = -1;
676 worker->pid = pid;
677 /* Wait for worker to become ready. */
678 readlen = lttcomm_recv_unix_sock(worker->sockpair[0],
679 &recvret, sizeof(recvret));
680 if (readlen < sizeof(recvret)) {
681 ERR("readlen: %zd", readlen);
682 PERROR("Error reading response from run_as at creation");
683 ret = -1;
684 goto error_fork;
685 }
686 global_worker = worker;
687 }
688end:
749b7a0c 689 pthread_mutex_unlock(&worker_lock);
7567352f
MD
690 return ret;
691
692 /* Error handling. */
693error_fork:
694 for (i = 0; i < 2; i++) {
695 if (worker->sockpair[i] < 0) {
696 continue;
697 }
698 if (lttcomm_close_unix_sock(worker->sockpair[i])) {
699 PERROR("close");
700 }
701 worker->sockpair[i] = -1;
702 }
703error_sock:
704 free(worker);
749b7a0c 705 pthread_mutex_unlock(&worker_lock);
7567352f
MD
706 return ret;
707}
708
709LTTNG_HIDDEN
710void run_as_destroy_worker(void)
711{
712 struct run_as_worker *worker = global_worker;
7567352f 713
978d5d79 714 DBG("Destroying run_as worker");
749b7a0c 715 pthread_mutex_lock(&worker_lock);
7567352f 716 if (!worker) {
749b7a0c 717 goto end;
7567352f
MD
718 }
719 /* Close unix socket */
978d5d79 720 DBG("Closing run_as worker socket");
7567352f
MD
721 if (lttcomm_close_unix_sock(worker->sockpair[0])) {
722 PERROR("close");
723 }
724 worker->sockpair[0] = -1;
725 /* Wait for worker. */
f8f66d38
JG
726 for (;;) {
727 int status;
728 pid_t wait_ret;
729
730 wait_ret = waitpid(worker->pid, &status, 0);
731 if (wait_ret < 0) {
732 if (errno == EINTR) {
733 continue;
734 }
735 PERROR("waitpid");
736 break;
737 }
738
739 if (WIFEXITED(status)) {
740 LOG(WEXITSTATUS(status) == 0 ? PRINT_DBG : PRINT_ERR,
741 DEFAULT_RUN_AS_WORKER_NAME " terminated with status code %d",
742 WEXITSTATUS(status));
743 break;
744 } else if (WIFSIGNALED(status)) {
745 ERR(DEFAULT_RUN_AS_WORKER_NAME " was killed by signal %d",
746 WTERMSIG(status));
747 break;
748 }
7567352f
MD
749 }
750 free(worker);
751 global_worker = NULL;
749b7a0c
JG
752end:
753 pthread_mutex_unlock(&worker_lock);
4628484a 754}
This page took 0.07647 seconds and 4 git commands to generate.