]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/journald-stream.c
tmpfiles: accurately report creation results
[thirdparty/systemd.git] / src / journal / journald-stream.c
CommitLineData
a45b9fca
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <fcntl.h>
23#include <unistd.h>
4871690d 24#include <stddef.h>
a45b9fca
LP
25
26#ifdef HAVE_SELINUX
27#include <selinux/selinux.h>
28#endif
29
f9a810be 30#include "sd-event.h"
13790add 31#include "sd-daemon.h"
a45b9fca 32#include "socket-util.h"
d682b3a7 33#include "selinux-util.h"
13790add
LP
34#include "mkdir.h"
35#include "fileio.h"
d025f1e4 36#include "journald-server.h"
a45b9fca
LP
37#include "journald-stream.h"
38#include "journald-syslog.h"
39#include "journald-kmsg.h"
3b7124a8 40#include "journald-console.h"
40b71e89 41#include "journald-wall.h"
a45b9fca
LP
42
43#define STDOUT_STREAMS_MAX 4096
44
45typedef enum StdoutStreamState {
46 STDOUT_STREAM_IDENTIFIER,
47 STDOUT_STREAM_UNIT_ID,
48 STDOUT_STREAM_PRIORITY,
49 STDOUT_STREAM_LEVEL_PREFIX,
50 STDOUT_STREAM_FORWARD_TO_SYSLOG,
51 STDOUT_STREAM_FORWARD_TO_KMSG,
52 STDOUT_STREAM_FORWARD_TO_CONSOLE,
53 STDOUT_STREAM_RUNNING
54} StdoutStreamState;
55
56struct StdoutStream {
57 Server *server;
58 StdoutStreamState state;
59
60 int fd;
61
62 struct ucred ucred;
63#ifdef HAVE_SELINUX
64 security_context_t security_context;
65#endif
66
67 char *identifier;
68 char *unit_id;
69 int priority;
70 bool level_prefix:1;
71 bool forward_to_syslog:1;
72 bool forward_to_kmsg:1;
73 bool forward_to_console:1;
74
13790add
LP
75 bool fdstore:1;
76
a45b9fca
LP
77 char buffer[LINE_MAX+1];
78 size_t length;
79
f9a810be
LP
80 sd_event_source *event_source;
81
13790add
LP
82 char *state_file;
83
a45b9fca
LP
84 LIST_FIELDS(StdoutStream, stdout_stream);
85};
86
13790add
LP
87void stdout_stream_free(StdoutStream *s) {
88 if (!s)
89 return;
90
91 if (s->server) {
92 assert(s->server->n_stdout_streams > 0);
93 s->server->n_stdout_streams --;
94 LIST_REMOVE(stdout_stream, s->server->stdout_streams, s);
95 }
96
97 if (s->event_source) {
98 sd_event_source_set_enabled(s->event_source, SD_EVENT_OFF);
99 s->event_source = sd_event_source_unref(s->event_source);
100 }
101
102 safe_close(s->fd);
103
104#ifdef HAVE_SELINUX
105 if (s->security_context)
106 freecon(s->security_context);
107#endif
108
109 free(s->identifier);
110 free(s->unit_id);
111 free(s->state_file);
112
113 free(s);
114}
115
116DEFINE_TRIVIAL_CLEANUP_FUNC(StdoutStream*, stdout_stream_free);
117
118static void stdout_stream_destroy(StdoutStream *s) {
119 if (!s)
120 return;
121
122 if (s->state_file)
123 unlink(s->state_file);
124
125 stdout_stream_free(s);
126}
127
128static int stdout_stream_save(StdoutStream *s) {
129 _cleanup_free_ char *temp_path = NULL;
130 _cleanup_fclose_ FILE *f = NULL;
131 int r;
132
133 assert(s);
134
135 if (s->state != STDOUT_STREAM_RUNNING)
136 return 0;
137
138 if (!s->state_file) {
139 struct stat st;
140
141 r = fstat(s->fd, &st);
142 if (r < 0)
143 return log_warning_errno(errno, "Failed to stat connected stream: %m");
144
145 /* We use device and inode numbers as identifier for the stream */
146 if (asprintf(&s->state_file, "/run/systemd/journal/streams/%lu:%lu", (unsigned long) st.st_dev, (unsigned long) st.st_ino) < 0)
147 return log_oom();
148 }
149
150 mkdir_p("/run/systemd/journal/streams", 0755);
151
152 r = fopen_temporary(s->state_file, &f, &temp_path);
153 if (r < 0)
154 goto finish;
155
156 fprintf(f,
157 "# This is private data. Do not parse\n"
158 "PRIORITY=%i\n"
159 "LEVEL_PREFIX=%i\n"
160 "FORWARD_TO_SYSLOG=%i\n"
161 "FORWARD_TO_KMSG=%i\n"
162 "FORWARD_TO_CONSOLE=%i\n",
163 s->priority,
164 s->level_prefix,
165 s->forward_to_syslog,
166 s->forward_to_kmsg,
167 s->forward_to_console);
168
169 if (!isempty(s->identifier)) {
170 _cleanup_free_ char *escaped;
171
172 escaped = cescape(s->identifier);
173 if (!escaped) {
174 r = -ENOMEM;
175 goto finish;
176 }
177
178 fprintf(f, "IDENTIFIER=%s\n", escaped);
179 }
180
181 if (!isempty(s->unit_id)) {
182 _cleanup_free_ char *escaped;
183
184 escaped = cescape(s->unit_id);
185 if (!escaped) {
186 r = -ENOMEM;
187 goto finish;
188 }
189
190 fprintf(f, "UNIT=%s\n", escaped);
191 }
192
193 r = fflush_and_check(f);
194 if (r < 0)
195 goto finish;
196
197 if (rename(temp_path, s->state_file) < 0) {
198 r = -errno;
199 goto finish;
200 }
201
202 free(temp_path);
203 temp_path = NULL;
204
205 /* Store the connection fd in PID 1, so that we get it passed
206 * in again on next start */
207 if (!s->fdstore) {
208 sd_pid_notify_with_fds(0, false, "FDSTORE=1", &s->fd, 1);
209 s->fdstore = true;
210 }
211
212finish:
213 if (temp_path)
214 unlink(temp_path);
215
216 if (r < 0)
217 log_error_errno(r, "Failed to save stream data %s: %m", s->state_file);
218
219 return r;
220}
221
a45b9fca
LP
222static int stdout_stream_log(StdoutStream *s, const char *p) {
223 struct iovec iovec[N_IOVEC_META_FIELDS + 5];
a45b9fca 224 int priority;
e3bfb7be
ZJS
225 char syslog_priority[] = "PRIORITY=\0";
226 char syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(priority)];
227 _cleanup_free_ char *message = NULL, *syslog_identifier = NULL;
228 unsigned n = 0;
a45b9fca
LP
229 char *label = NULL;
230 size_t label_len = 0;
231
232 assert(s);
233 assert(p);
234
235 if (isempty(p))
236 return 0;
237
238 priority = s->priority;
239
240 if (s->level_prefix)
e3bfb7be 241 syslog_parse_priority(&p, &priority, false);
a45b9fca
LP
242
243 if (s->forward_to_syslog || s->server->forward_to_syslog)
244 server_forward_syslog(s->server, syslog_fixup_facility(priority), s->identifier, p, &s->ucred, NULL);
245
246 if (s->forward_to_kmsg || s->server->forward_to_kmsg)
247 server_forward_kmsg(s->server, priority, s->identifier, p, &s->ucred);
248
249 if (s->forward_to_console || s->server->forward_to_console)
250 server_forward_console(s->server, priority, s->identifier, p, &s->ucred);
251
40b71e89
ST
252 if (s->server->forward_to_wall)
253 server_forward_wall(s->server, priority, s->identifier, p, &s->ucred);
254
a45b9fca
LP
255 IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=stdout");
256
e3bfb7be
ZJS
257 syslog_priority[strlen("PRIORITY=")] = '0' + LOG_PRI(priority);
258 IOVEC_SET_STRING(iovec[n++], syslog_priority);
a45b9fca 259
e3bfb7be
ZJS
260 if (priority & LOG_FACMASK) {
261 snprintf(syslog_facility, sizeof(syslog_facility), "SYSLOG_FACILITY=%i", LOG_FAC(priority));
262 IOVEC_SET_STRING(iovec[n++], syslog_facility);
263 }
a45b9fca
LP
264
265 if (s->identifier) {
266 syslog_identifier = strappend("SYSLOG_IDENTIFIER=", s->identifier);
267 if (syslog_identifier)
268 IOVEC_SET_STRING(iovec[n++], syslog_identifier);
269 }
270
271 message = strappend("MESSAGE=", p);
272 if (message)
273 IOVEC_SET_STRING(iovec[n++], message);
274
275#ifdef HAVE_SELINUX
276 if (s->security_context) {
277 label = (char*) s->security_context;
278 label_len = strlen((char*) s->security_context);
279 }
280#endif
281
968f3196 282 server_dispatch_message(s->server, iovec, n, ELEMENTSOF(iovec), &s->ucred, NULL, label, label_len, s->unit_id, priority, 0);
a45b9fca
LP
283 return 0;
284}
285
286static int stdout_stream_line(StdoutStream *s, char *p) {
287 int r;
288
289 assert(s);
290 assert(p);
291
292 p = strstrip(p);
293
294 switch (s->state) {
295
296 case STDOUT_STREAM_IDENTIFIER:
297 if (isempty(p))
298 s->identifier = NULL;
299 else {
300 s->identifier = strdup(p);
301 if (!s->identifier)
302 return log_oom();
303 }
304
305 s->state = STDOUT_STREAM_UNIT_ID;
306 return 0;
307
308 case STDOUT_STREAM_UNIT_ID:
309 if (s->ucred.uid == 0) {
310 if (isempty(p))
311 s->unit_id = NULL;
312 else {
313 s->unit_id = strdup(p);
314 if (!s->unit_id)
315 return log_oom();
316 }
317 }
318
319 s->state = STDOUT_STREAM_PRIORITY;
320 return 0;
321
322 case STDOUT_STREAM_PRIORITY:
323 r = safe_atoi(p, &s->priority);
41891700 324 if (r < 0 || s->priority < 0 || s->priority > 999) {
a45b9fca
LP
325 log_warning("Failed to parse log priority line.");
326 return -EINVAL;
327 }
328
329 s->state = STDOUT_STREAM_LEVEL_PREFIX;
330 return 0;
331
332 case STDOUT_STREAM_LEVEL_PREFIX:
333 r = parse_boolean(p);
334 if (r < 0) {
335 log_warning("Failed to parse level prefix line.");
336 return -EINVAL;
337 }
338
339 s->level_prefix = !!r;
340 s->state = STDOUT_STREAM_FORWARD_TO_SYSLOG;
341 return 0;
342
343 case STDOUT_STREAM_FORWARD_TO_SYSLOG:
344 r = parse_boolean(p);
345 if (r < 0) {
346 log_warning("Failed to parse forward to syslog line.");
347 return -EINVAL;
348 }
349
350 s->forward_to_syslog = !!r;
351 s->state = STDOUT_STREAM_FORWARD_TO_KMSG;
352 return 0;
353
354 case STDOUT_STREAM_FORWARD_TO_KMSG:
355 r = parse_boolean(p);
356 if (r < 0) {
357 log_warning("Failed to parse copy to kmsg line.");
358 return -EINVAL;
359 }
360
361 s->forward_to_kmsg = !!r;
362 s->state = STDOUT_STREAM_FORWARD_TO_CONSOLE;
363 return 0;
364
365 case STDOUT_STREAM_FORWARD_TO_CONSOLE:
366 r = parse_boolean(p);
367 if (r < 0) {
368 log_warning("Failed to parse copy to console line.");
369 return -EINVAL;
370 }
371
372 s->forward_to_console = !!r;
373 s->state = STDOUT_STREAM_RUNNING;
13790add
LP
374
375 /* Try to save the stream, so that journald can be restarted and we can recover */
376 (void) stdout_stream_save(s);
a45b9fca
LP
377 return 0;
378
379 case STDOUT_STREAM_RUNNING:
380 return stdout_stream_log(s, p);
381 }
382
383 assert_not_reached("Unknown stream state");
384}
385
386static int stdout_stream_scan(StdoutStream *s, bool force_flush) {
387 char *p;
388 size_t remaining;
389 int r;
390
391 assert(s);
392
393 p = s->buffer;
394 remaining = s->length;
395 for (;;) {
396 char *end;
397 size_t skip;
398
399 end = memchr(p, '\n', remaining);
400 if (end)
401 skip = end - p + 1;
402 else if (remaining >= sizeof(s->buffer) - 1) {
403 end = p + sizeof(s->buffer) - 1;
404 skip = remaining;
405 } else
406 break;
407
408 *end = 0;
409
410 r = stdout_stream_line(s, p);
411 if (r < 0)
412 return r;
413
414 remaining -= skip;
415 p += skip;
416 }
417
418 if (force_flush && remaining > 0) {
419 p[remaining] = 0;
420 r = stdout_stream_line(s, p);
421 if (r < 0)
422 return r;
423
424 p += remaining;
425 remaining = 0;
426 }
427
428 if (p > s->buffer) {
429 memmove(s->buffer, p, remaining);
430 s->length = remaining;
431 }
432
433 return 0;
434}
435
f9a810be
LP
436static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
437 StdoutStream *s = userdata;
a45b9fca
LP
438 ssize_t l;
439 int r;
440
441 assert(s);
442
f9a810be
LP
443 if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) {
444 log_error("Got invalid event from epoll for stdout stream: %"PRIx32, revents);
91bf3b3e 445 goto terminate;
f9a810be
LP
446 }
447
a45b9fca
LP
448 l = read(s->fd, s->buffer+s->length, sizeof(s->buffer)-1-s->length);
449 if (l < 0) {
450
451 if (errno == EAGAIN)
452 return 0;
453
56f64d95 454 log_warning_errno(errno, "Failed to read from stream: %m");
91bf3b3e 455 goto terminate;
a45b9fca
LP
456 }
457
458 if (l == 0) {
7b77ed8c 459 stdout_stream_scan(s, true);
91bf3b3e 460 goto terminate;
a45b9fca
LP
461 }
462
463 s->length += l;
464 r = stdout_stream_scan(s, false);
465 if (r < 0)
91bf3b3e 466 goto terminate;
a45b9fca
LP
467
468 return 1;
469
91bf3b3e 470terminate:
13790add 471 stdout_stream_destroy(s);
f9a810be 472 return 0;
a45b9fca
LP
473}
474
13790add
LP
475static int stdout_stream_install(Server *s, int fd, StdoutStream **ret) {
476 _cleanup_(stdout_stream_freep) StdoutStream *stream = NULL;
477 int r;
478
a45b9fca 479 assert(s);
13790add 480 assert(fd >= 0);
a45b9fca 481
13790add
LP
482 stream = new0(StdoutStream, 1);
483 if (!stream)
484 return log_oom();
a45b9fca 485
13790add
LP
486 stream->fd = -1;
487 stream->priority = LOG_INFO;
a45b9fca 488
13790add
LP
489 r = getpeercred(fd, &stream->ucred);
490 if (r < 0)
491 return log_error_errno(r, "Failed to determine peer credentials: %m");
a45b9fca
LP
492
493#ifdef HAVE_SELINUX
13790add
LP
494 if (mac_selinux_use()) {
495 if (getpeercon(fd, &stream->security_context) < 0 && errno != ENOPROTOOPT)
496 log_error_errno(errno, "Failed to determine peer security context: %m");
497 }
a45b9fca
LP
498#endif
499
13790add
LP
500 (void) shutdown(fd, SHUT_WR);
501
502 r = sd_event_add_io(s->event, &stream->event_source, fd, EPOLLIN, stdout_stream_process, stream);
503 if (r < 0)
504 return log_error_errno(r, "Failed to add stream to event loop: %m");
505
506 r = sd_event_source_set_priority(stream->event_source, SD_EVENT_PRIORITY_NORMAL+5);
507 if (r < 0)
508 return log_error_errno(r, "Failed to adjust stdout event source priority: %m");
509
510 stream->fd = fd;
511
512 stream->server = s;
513 LIST_PREPEND(stdout_stream, s->stdout_streams, stream);
514 s->n_stdout_streams ++;
515
516 if (ret)
517 *ret = stream;
518
519 stream = NULL;
520
521 return 0;
a45b9fca
LP
522}
523
f9a810be 524static int stdout_stream_new(sd_event_source *es, int listen_fd, uint32_t revents, void *userdata) {
13790add 525 _cleanup_close_ int fd = -1;
f9a810be 526 Server *s = userdata;
13790add 527 int r;
a45b9fca
LP
528
529 assert(s);
530
f9a810be
LP
531 if (revents != EPOLLIN) {
532 log_error("Got invalid event from epoll for stdout server fd: %"PRIx32, revents);
533 return -EIO;
534 }
535
a45b9fca
LP
536 fd = accept4(s->stdout_fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
537 if (fd < 0) {
538 if (errno == EAGAIN)
539 return 0;
540
56f64d95 541 log_error_errno(errno, "Failed to accept stdout connection: %m");
a45b9fca
LP
542 return -errno;
543 }
544
545 if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
546 log_warning("Too many stdout streams, refusing connection.");
a45b9fca
LP
547 return 0;
548 }
549
13790add
LP
550 r = stdout_stream_install(s, fd, NULL);
551 if (r < 0)
552 return r;
553
554 fd = -1;
555 return 0;
556}
557
558static int stdout_stream_load(StdoutStream *stream, const char *fname) {
559 _cleanup_free_ char
560 *priority = NULL,
561 *level_prefix = NULL,
562 *forward_to_syslog = NULL,
563 *forward_to_kmsg = NULL,
564 *forward_to_console = NULL;
565 int r;
566
567 assert(stream);
568 assert(fname);
569
570 if (!stream->state_file) {
571 stream->state_file = strappend("/run/systemd/journal/streams/", fname);
572 if (!stream->state_file)
573 return log_oom();
a45b9fca
LP
574 }
575
13790add
LP
576 r = parse_env_file(stream->state_file, NEWLINE,
577 "PRIORITY", &priority,
578 "LEVEL_PREFIX", &level_prefix,
579 "FORWARD_TO_SYSLOG", &forward_to_syslog,
580 "FORWARD_TO_KMSG", &forward_to_kmsg,
581 "FORWARD_TO_CONSOLE", &forward_to_console,
582 "IDENTIFIER", &stream->identifier,
583 "UNIT", &stream->unit_id,
584 NULL);
585 if (r < 0)
586 return log_error_errno(r, "Failed to read: %s", stream->state_file);
a45b9fca 587
13790add
LP
588 if (priority) {
589 int p;
590
591 p = log_level_from_string(priority);
592 if (p >= 0)
593 stream->priority = p;
a45b9fca
LP
594 }
595
13790add
LP
596 if (level_prefix) {
597 r = parse_boolean(level_prefix);
598 if (r >= 0)
599 stream->level_prefix = r;
d682b3a7 600 }
a45b9fca 601
13790add
LP
602 if (forward_to_syslog) {
603 r = parse_boolean(forward_to_syslog);
604 if (r >= 0)
605 stream->forward_to_syslog = r;
a45b9fca
LP
606 }
607
13790add
LP
608 if (forward_to_kmsg) {
609 r = parse_boolean(forward_to_kmsg);
610 if (r >= 0)
611 stream->forward_to_kmsg = r;
f9a810be
LP
612 }
613
13790add
LP
614 if (forward_to_console) {
615 r = parse_boolean(forward_to_console);
616 if (r >= 0)
617 stream->forward_to_console = r;
a45b9fca
LP
618 }
619
13790add
LP
620 return 0;
621}
622
623static int stdout_stream_restore(Server *s, const char *fname, int fd) {
624 StdoutStream *stream;
625 int r;
626
627 assert(s);
628 assert(fname);
629 assert(fd >= 0);
630
631 if (s->n_stdout_streams >= STDOUT_STREAMS_MAX) {
632 log_warning("Too many stdout streams, refusing restoring of stream.");
633 return -ENOBUFS;
634 }
635
636 r = stdout_stream_install(s, fd, &stream);
637 if (r < 0)
638 return r;
639
640 stream->state = STDOUT_STREAM_RUNNING;
641 stream->fdstore = true;
642
643 /* Ignore all parsing errors */
644 (void) stdout_stream_load(stream, fname);
a45b9fca
LP
645
646 return 0;
13790add
LP
647}
648
649static int server_restore_streams(Server *s, FDSet *fds) {
650 _cleanup_closedir_ DIR *d = NULL;
651 struct dirent *de;
652 int r;
653
654 d = opendir("/run/systemd/journal/streams");
655 if (!d) {
656 if (errno == ENOENT)
657 return 0;
658
659 return log_warning_errno(errno, "Failed to enumerate /run/systemd/journal/streams: %m");
660 }
661
662 FOREACH_DIRENT(de, d, goto fail) {
663 unsigned long st_dev, st_ino;
664 bool found = false;
665 Iterator i;
666 int fd;
667
668 if (sscanf(de->d_name, "%lu:%lu", &st_dev, &st_ino) != 2)
669 continue;
670
671 FDSET_FOREACH(fd, fds, i) {
672 struct stat st;
673
674 if (fstat(fd, &st) < 0)
675 return log_error_errno(errno, "Failed to stat %s: %m", de->d_name);
676
677 if (S_ISSOCK(st.st_mode) && st.st_dev == st_dev && st.st_ino == st_ino) {
678 found = true;
679 break;
680 }
681 }
682
683 if (!found) {
684 /* No file descriptor? Then let's delete the state file */
685 log_debug("Cannot restore stream file %s", de->d_name);
686 unlinkat(dirfd(d), de->d_name, 0);
687 continue;
688 }
689
690 fdset_remove(fds, fd);
691
692 r = stdout_stream_restore(s, de->d_name, fd);
693 if (r < 0)
694 safe_close(fd);
695 }
a45b9fca 696
7b77ed8c 697 return 0;
13790add
LP
698
699fail:
700 return log_error_errno(errno, "Failed to read streams directory: %m");
a45b9fca
LP
701}
702
13790add 703int server_open_stdout_socket(Server *s, FDSet *fds) {
a45b9fca 704 int r;
a45b9fca
LP
705
706 assert(s);
707
708 if (s->stdout_fd < 0) {
b92bea5d
ZJS
709 union sockaddr_union sa = {
710 .un.sun_family = AF_UNIX,
711 .un.sun_path = "/run/systemd/journal/stdout",
712 };
a45b9fca
LP
713
714 s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
4a62c710
MS
715 if (s->stdout_fd < 0)
716 return log_error_errno(errno, "socket() failed: %m");
a45b9fca 717
a45b9fca
LP
718 unlink(sa.un.sun_path);
719
720 r = bind(s->stdout_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path));
4a62c710
MS
721 if (r < 0)
722 return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);
a45b9fca
LP
723
724 chmod(sa.un.sun_path, 0666);
725
4a62c710
MS
726 if (listen(s->stdout_fd, SOMAXCONN) < 0)
727 return log_error_errno(errno, "listen(%s) failed: %m", sa.un.sun_path);
a45b9fca
LP
728 } else
729 fd_nonblock(s->stdout_fd, 1);
730
151b9b96 731 r = sd_event_add_io(s->event, &s->stdout_event_source, s->stdout_fd, EPOLLIN, stdout_stream_new, s);
23bbb0de
MS
732 if (r < 0)
733 return log_error_errno(r, "Failed to add stdout server fd to event source: %m");
f9a810be
LP
734
735 r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+10);
23bbb0de
MS
736 if (r < 0)
737 return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m");
a45b9fca 738
13790add
LP
739 /* Try to restore streams, but don't bother if this fails */
740 (void) server_restore_streams(s, fds);
741
a45b9fca
LP
742 return 0;
743}