]> git.ipfire.org Git - people/ms/systemd.git/blame - socket.c
cgroup: add cgroupsification
[people/ms/systemd.git] / socket.c
CommitLineData
5cb5a6ff
LP
1/*-*- Mode: C; c-basic-offset: 8 -*-*/
2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 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 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
83c60c9f
LP
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include <errno.h>
26#include <fcntl.h>
f94ea366 27#include <sys/epoll.h>
034c6ed7 28#include <signal.h>
83c60c9f 29
87f0e418 30#include "unit.h"
5cb5a6ff 31#include "socket.h"
83c60c9f
LP
32#include "log.h"
33
acbb0225 34static const UnitActiveState state_translation_table[_SOCKET_STATE_MAX] = {
87f0e418
LP
35 [SOCKET_DEAD] = UNIT_INACTIVE,
36 [SOCKET_START_PRE] = UNIT_ACTIVATING,
37 [SOCKET_START_POST] = UNIT_ACTIVATING,
38 [SOCKET_LISTENING] = UNIT_ACTIVE,
39 [SOCKET_RUNNING] = UNIT_ACTIVE,
40 [SOCKET_STOP_PRE] = UNIT_DEACTIVATING,
41 [SOCKET_STOP_PRE_SIGTERM] = UNIT_DEACTIVATING,
42 [SOCKET_STOP_PRE_SIGKILL] = UNIT_DEACTIVATING,
43 [SOCKET_STOP_POST] = UNIT_DEACTIVATING,
44 [SOCKET_STOP_POST_SIGTERM] = UNIT_DEACTIVATING,
45 [SOCKET_STOP_POST_SIGKILL] = UNIT_DEACTIVATING,
46 [SOCKET_MAINTAINANCE] = UNIT_INACTIVE,
83c60c9f 47};
5cb5a6ff 48
acbb0225
LP
49static const char* const state_string_table[_SOCKET_STATE_MAX] = {
50 [SOCKET_DEAD] = "dead",
51 [SOCKET_START_PRE] = "start-pre",
52 [SOCKET_START_POST] = "start-post",
53 [SOCKET_LISTENING] = "listening",
54 [SOCKET_RUNNING] = "running",
55 [SOCKET_STOP_PRE] = "stop-pre",
56 [SOCKET_STOP_PRE_SIGTERM] = "stop-pre-sigterm",
57 [SOCKET_STOP_PRE_SIGKILL] = "stop-pre-sigkill",
58 [SOCKET_STOP_POST] = "stop-post",
59 [SOCKET_STOP_POST_SIGTERM] = "stop-post-sigterm",
60 [SOCKET_STOP_POST_SIGKILL] = "stop-post-sigkill",
61 [SOCKET_MAINTAINANCE] = "maintainance"
62};
63
87f0e418
LP
64static void socket_done(Unit *u) {
65 Socket *s = SOCKET(u);
034c6ed7
LP
66 SocketPort *p;
67
68 assert(s);
69
70 while ((p = s->ports)) {
71 LIST_REMOVE(SocketPort, port, s->ports, p);
72
73 if (p->fd >= 0)
74 close_nointr(p->fd);
75 free(p->path);
76 free(p);
77 }
78
79 exec_context_done(&s->exec_context);
80 exec_command_free_array(s->exec_command, _SOCKET_EXEC_MAX);
81 s->control_command = NULL;
82
83 if (s->control_pid > 0) {
87f0e418 84 unit_unwatch_pid(u, s->control_pid);
034c6ed7
LP
85 s->control_pid = 0;
86 }
87
88 s->service = NULL;
89
acbb0225
LP
90 free(s->bind_to_device);
91
92 unit_unwatch_timer(u, &s->timer_watch);
5cb5a6ff
LP
93}
94
87f0e418
LP
95static int socket_init(Unit *u) {
96 Socket *s = SOCKET(u);
44d8db9e
LP
97 char *t;
98 int r;
99
100 /* First, reset everything to the defaults, in case this is a
101 * reload */
102
103 s->state = 0;
acbb0225 104 s->timer_watch.type = WATCH_INVALID;
44d8db9e
LP
105 s->bind_ipv6_only = false;
106 s->backlog = SOMAXCONN;
107 s->timeout_usec = DEFAULT_TIMEOUT_USEC;
b5a0699f
LP
108 s->directory_mode = 0755;
109 s->socket_mode = 0666;
44d8db9e
LP
110 exec_context_init(&s->exec_context);
111
d46de8a1
LP
112 if ((r = unit_load_fragment_and_dropin(u)) <= 0) {
113 if (r == 0)
114 r = -ENOENT;
44d8db9e 115 goto fail;
d46de8a1 116 }
44d8db9e 117
87f0e418 118 if (!(t = unit_name_change_suffix(unit_id(u), ".service"))) {
44d8db9e
LP
119 r = -ENOMEM;
120 goto fail;
121 }
122
87f0e418 123 r = manager_load_unit(u->meta.manager, t, (Unit**) &s->service);
44d8db9e
LP
124 free(t);
125
126 if (r < 0)
127 goto fail;
128
87f0e418 129 if ((r = unit_add_dependency(u, UNIT_BEFORE, UNIT(s->service))) < 0)
44d8db9e
LP
130 goto fail;
131
8e274523
LP
132 /* Add default cgroup */
133 if ((r = unit_add_default_cgroup(u)) < 0)
134 goto fail;
135
44d8db9e
LP
136 return 0;
137
138fail:
87f0e418 139 socket_done(u);
44d8db9e
LP
140 return r;
141}
142
542563ba
LP
143static const char* listen_lookup(int type) {
144
145 if (type == SOCK_STREAM)
146 return "ListenStream";
147 else if (type == SOCK_DGRAM)
148 return "ListenDatagram";
149 else if (type == SOCK_SEQPACKET)
150 return "ListenSequentialPacket";
151
034c6ed7 152 assert_not_reached("Unknown socket type");
542563ba
LP
153 return NULL;
154}
155
87f0e418 156static void socket_dump(Unit *u, FILE *f, const char *prefix) {
5cb5a6ff 157
5cb5a6ff
LP
158 static const char* const command_table[_SOCKET_EXEC_MAX] = {
159 [SOCKET_EXEC_START_PRE] = "StartPre",
160 [SOCKET_EXEC_START_POST] = "StartPost",
161 [SOCKET_EXEC_STOP_PRE] = "StopPre",
162 [SOCKET_EXEC_STOP_POST] = "StopPost"
163 };
164
165 SocketExecCommand c;
87f0e418 166 Socket *s = SOCKET(u);
542563ba 167 SocketPort *p;
82ba9f08
LP
168 const char *prefix2;
169 char *p2;
5cb5a6ff
LP
170
171 assert(s);
fa068367 172 assert(f);
5cb5a6ff 173
82ba9f08
LP
174 p2 = strappend(prefix, "\t");
175 prefix2 = p2 ? p2 : prefix;
c43d20a0 176
5cb5a6ff
LP
177 fprintf(f,
178 "%sSocket State: %s\n"
542563ba 179 "%sBindIPv6Only: %s\n"
b5a0699f
LP
180 "%sBacklog: %u\n"
181 "%sSocketMode: %04o\n"
182 "%sDirectoryMode: %04o\n",
acbb0225 183 prefix, state_string_table[s->state],
542563ba 184 prefix, yes_no(s->bind_ipv6_only),
b5a0699f
LP
185 prefix, s->backlog,
186 prefix, s->socket_mode,
187 prefix, s->directory_mode);
542563ba 188
acbb0225
LP
189 if (s->bind_to_device)
190 fprintf(f,
191 "%sBindToDevice: %s\n",
192 prefix, s->bind_to_device);
193
034c6ed7 194 LIST_FOREACH(port, p, s->ports) {
5cb5a6ff 195
542563ba
LP
196 if (p->type == SOCKET_SOCKET) {
197 const char *t;
198 int r;
199 char *k;
200
201 if ((r = socket_address_print(&p->address, &k)) < 0)
202 t = strerror(-r);
203 else
204 t = k;
205
206 fprintf(f, "%s%s: %s\n", prefix, listen_lookup(p->address.type), k);
207 free(k);
208 } else
209 fprintf(f, "%sListenFIFO: %s\n", prefix, p->path);
210 }
5cb5a6ff
LP
211
212 exec_context_dump(&s->exec_context, f, prefix);
213
214 for (c = 0; c < _SOCKET_EXEC_MAX; c++) {
c43d20a0
LP
215 if (!s->exec_command[c])
216 continue;
5cb5a6ff 217
c43d20a0
LP
218 fprintf(f, "%s→ %s:\n",
219 prefix, command_table[c]);
220
221 exec_command_dump_list(s->exec_command[c], f, prefix2);
5cb5a6ff 222 }
c43d20a0 223
82ba9f08 224 free(p2);
5cb5a6ff
LP
225}
226
034c6ed7 227static void socket_close_fds(Socket *s) {
83c60c9f
LP
228 SocketPort *p;
229
230 assert(s);
231
034c6ed7 232 LIST_FOREACH(port, p, s->ports) {
83c60c9f
LP
233 if (p->fd < 0)
234 continue;
235
acbb0225 236 unit_unwatch_fd(UNIT(s), &p->fd_watch);
9152c765
LP
237 assert_se(close_nointr(p->fd) >= 0);
238
83c60c9f
LP
239 p->fd = -1;
240 }
241}
242
034c6ed7 243static int socket_open_fds(Socket *s) {
83c60c9f
LP
244 SocketPort *p;
245 int r;
246
247 assert(s);
248
034c6ed7 249 LIST_FOREACH(port, p, s->ports) {
83c60c9f 250
034c6ed7
LP
251 if (p->fd >= 0)
252 continue;
83c60c9f
LP
253
254 if (p->type == SOCKET_SOCKET) {
255
b5a0699f
LP
256 if ((r = socket_address_listen(
257 &p->address,
258 s->backlog,
259 s->bind_ipv6_only,
260 s->bind_to_device,
261 s->directory_mode,
262 s->socket_mode,
263 &p->fd)) < 0)
83c60c9f
LP
264 goto rollback;
265
266 } else {
267 struct stat st;
268 assert(p->type == SOCKET_FIFO);
269
270 if (mkfifo(p->path, 0666 & ~s->exec_context.umask) < 0 && errno != EEXIST) {
271 r = -errno;
272 goto rollback;
273 }
274
275 if ((p->fd = open(p->path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW)) < 0) {
276 r = -errno;
277 goto rollback;
278 }
279
280 if (fstat(p->fd, &st) < 0) {
281 r = -errno;
282 goto rollback;
283 }
284
285 /* FIXME verify user, access mode */
286
287 if (!S_ISFIFO(st.st_mode)) {
288 r = -EEXIST;
289 goto rollback;
290 }
291 }
034c6ed7
LP
292 }
293
294 return 0;
295
296rollback:
297 socket_close_fds(s);
298 return r;
299}
300
301static void socket_unwatch_fds(Socket *s) {
302 SocketPort *p;
9152c765 303
034c6ed7
LP
304 assert(s);
305
306 LIST_FOREACH(port, p, s->ports) {
307 if (p->fd < 0)
308 continue;
309
acbb0225 310 unit_unwatch_fd(UNIT(s), &p->fd_watch);
83c60c9f 311 }
034c6ed7
LP
312}
313
314static int socket_watch_fds(Socket *s) {
315 SocketPort *p;
316 int r;
317
318 assert(s);
83c60c9f 319
034c6ed7
LP
320 LIST_FOREACH(port, p, s->ports) {
321 if (p->fd < 0)
322 continue;
323
f94ea366 324 if ((r = unit_watch_fd(UNIT(s), p->fd, EPOLLIN, &p->fd_watch)) < 0)
034c6ed7
LP
325 goto fail;
326 }
83c60c9f 327
542563ba 328 return 0;
83c60c9f 329
034c6ed7
LP
330fail:
331 socket_unwatch_fds(s);
332 return r;
333}
334
335static void socket_set_state(Socket *s, SocketState state) {
336 SocketState old_state;
337 assert(s);
338
339 old_state = s->state;
340 s->state = state;
341
342 if (state != SOCKET_START_PRE &&
343 state != SOCKET_START_POST &&
344 state != SOCKET_STOP_PRE &&
345 state != SOCKET_STOP_PRE_SIGTERM &&
346 state != SOCKET_STOP_PRE_SIGKILL &&
347 state != SOCKET_STOP_POST &&
348 state != SOCKET_STOP_POST_SIGTERM &&
349 state != SOCKET_STOP_POST_SIGKILL)
acbb0225 350 unit_unwatch_timer(UNIT(s), &s->timer_watch);
034c6ed7
LP
351
352 if (state != SOCKET_START_PRE &&
353 state != SOCKET_START_POST &&
354 state != SOCKET_STOP_PRE &&
355 state != SOCKET_STOP_PRE_SIGTERM &&
356 state != SOCKET_STOP_PRE_SIGKILL &&
357 state != SOCKET_STOP_POST &&
358 state != SOCKET_STOP_POST_SIGTERM &&
359 state != SOCKET_STOP_POST_SIGKILL)
acbb0225 360 if (s->control_pid > 0) {
87f0e418 361 unit_unwatch_pid(UNIT(s), s->control_pid);
034c6ed7
LP
362 s->control_pid = 0;
363 }
364
365 if (state != SOCKET_START_PRE &&
366 state != SOCKET_START_POST &&
367 state != SOCKET_STOP_PRE &&
368 state != SOCKET_STOP_POST)
369 s->control_command = NULL;
370
371 if (state != SOCKET_START_POST &&
372 state != SOCKET_LISTENING &&
373 state != SOCKET_RUNNING &&
374 state != SOCKET_STOP_PRE &&
375 state != SOCKET_STOP_PRE_SIGTERM &&
376 state != SOCKET_STOP_PRE_SIGKILL)
377 socket_close_fds(s);
378
379 if (state != SOCKET_LISTENING)
380 socket_unwatch_fds(s);
381
d6ea93e3 382 log_debug("%s changed %s → %s", unit_id(UNIT(s)), state_string_table[old_state], state_string_table[state]);
acbb0225
LP
383
384 unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state]);
034c6ed7
LP
385}
386
387static int socket_spawn(Socket *s, ExecCommand *c, bool timeout, pid_t *_pid) {
388 pid_t pid;
389 int r;
390
391 assert(s);
392 assert(c);
393 assert(_pid);
394
395 if (timeout) {
acbb0225 396 if ((r = unit_watch_timer(UNIT(s), s->timeout_usec, &s->timer_watch)) < 0)
034c6ed7
LP
397 goto fail;
398 } else
acbb0225 399 unit_unwatch_timer(UNIT(s), &s->timer_watch);
034c6ed7 400
8e274523
LP
401 if ((r = exec_spawn(c,
402 &s->exec_context,
403 NULL, 0,
404 true,
405 true,
406 UNIT(s)->meta.cgroup_bondings,
407 &pid)) < 0)
034c6ed7
LP
408 goto fail;
409
87f0e418 410 if ((r = unit_watch_pid(UNIT(s), pid)) < 0)
034c6ed7
LP
411 /* FIXME: we need to do something here */
412 goto fail;
83c60c9f 413
034c6ed7
LP
414 *_pid = pid;
415
416 return 0;
417
418fail:
419 if (timeout)
acbb0225 420 unit_unwatch_timer(UNIT(s), &s->timer_watch);
83c60c9f
LP
421
422 return r;
542563ba
LP
423}
424
034c6ed7
LP
425static void socket_enter_dead(Socket *s, bool success) {
426 assert(s);
427
428 if (!success)
429 s->failure = true;
430
431 socket_set_state(s, s->failure ? SOCKET_MAINTAINANCE : SOCKET_DEAD);
432}
433
434static void socket_enter_stop_post(Socket *s, bool success) {
435 int r;
436 assert(s);
437
438 if (!success)
439 s->failure = true;
440
d6ea93e3 441 if ((s->control_command = s->exec_command[SOCKET_EXEC_STOP_POST]))
034c6ed7
LP
442 if ((r = socket_spawn(s, s->control_command, true, &s->control_pid)) < 0)
443 goto fail;
444
d6ea93e3
LP
445 socket_set_state(s, SOCKET_STOP_POST);
446
447 if (!s->control_command)
034c6ed7
LP
448 socket_enter_dead(s, true);
449
450 return;
451
452fail:
87f0e418 453 log_warning("%s failed to run stop-post executable: %s", unit_id(UNIT(s)), strerror(-r));
034c6ed7
LP
454 socket_enter_dead(s, false);
455}
456
457static void socket_enter_signal(Socket *s, SocketState state, bool success) {
458 int r;
459
460 assert(s);
461
462 if (!success)
463 s->failure = true;
464
465 if (s->control_pid > 0) {
466 int sig;
467
468 sig = (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_STOP_POST_SIGTERM) ? SIGTERM : SIGKILL;
469
470 if (kill(s->control_pid, sig) < 0 && errno != ESRCH) {
471 r = -errno;
472 goto fail;
473 }
d6ea93e3 474 }
034c6ed7 475
d6ea93e3
LP
476 socket_set_state(s, state);
477
478 if (s->control_pid <= 0)
034c6ed7
LP
479 socket_enter_dead(s, true);
480
481 return;
482
483fail:
87f0e418 484 log_warning("%s failed to kill processes: %s", unit_id(UNIT(s)), strerror(-r));
034c6ed7
LP
485
486 if (state == SOCKET_STOP_PRE_SIGTERM || state == SOCKET_STOP_PRE_SIGKILL)
487 socket_enter_stop_post(s, false);
488 else
489 socket_enter_dead(s, false);
490}
491
492static void socket_enter_stop_pre(Socket *s, bool success) {
493 int r;
494 assert(s);
495
496 if (!success)
497 s->failure = true;
498
d6ea93e3 499 if ((s->control_command = s->exec_command[SOCKET_EXEC_STOP_PRE]))
034c6ed7
LP
500 if ((r = socket_spawn(s, s->control_command, true, &s->control_pid)) < 0)
501 goto fail;
502
d6ea93e3
LP
503 socket_set_state(s, SOCKET_STOP_PRE);
504
505 if (!s->control_command)
034c6ed7
LP
506 socket_enter_stop_post(s, true);
507
508 return;
509
510fail:
87f0e418 511 log_warning("%s failed to run stop-pre executable: %s", unit_id(UNIT(s)), strerror(-r));
034c6ed7
LP
512 socket_enter_stop_post(s, false);
513}
514
e9af15c3
LP
515static void socket_enter_listening(Socket *s) {
516 int r;
517 assert(s);
518
519 if ((r = socket_watch_fds(s)) < 0) {
520 log_warning("%s failed to watch sockets: %s", unit_id(UNIT(s)), strerror(-r));
521 goto fail;
522 }
523
524 socket_set_state(s, SOCKET_LISTENING);
525 return;
526
527fail:
528 socket_enter_stop_pre(s, false);
529}
530
034c6ed7
LP
531static void socket_enter_start_post(Socket *s) {
532 int r;
533 assert(s);
534
e9af15c3 535 if ((r = socket_open_fds(s)) < 0) {
87f0e418 536 log_warning("%s failed to listen on sockets: %s", unit_id(UNIT(s)), strerror(-r));
034c6ed7
LP
537 goto fail;
538 }
539
d6ea93e3 540 if ((s->control_command = s->exec_command[SOCKET_EXEC_START_POST]))
034c6ed7 541 if ((r = socket_spawn(s, s->control_command, true, &s->control_pid)) < 0) {
87f0e418 542 log_warning("%s failed to run start-post executable: %s", unit_id(UNIT(s)), strerror(-r));
034c6ed7
LP
543 goto fail;
544 }
545
d6ea93e3
LP
546 socket_set_state(s, SOCKET_START_POST);
547
548 if (!s->control_command)
e9af15c3 549 socket_enter_listening(s);
034c6ed7
LP
550
551 return;
552
553fail:
554 socket_enter_stop_pre(s, false);
555}
556
557static void socket_enter_start_pre(Socket *s) {
558 int r;
559 assert(s);
560
d6ea93e3 561 if ((s->control_command = s->exec_command[SOCKET_EXEC_START_PRE]))
034c6ed7
LP
562 if ((r = socket_spawn(s, s->control_command, true, &s->control_pid)) < 0)
563 goto fail;
564
d6ea93e3
LP
565 socket_set_state(s, SOCKET_START_PRE);
566
567 if (!s->control_command)
034c6ed7
LP
568 socket_enter_start_post(s);
569
570 return;
571
572fail:
87f0e418 573 log_warning("%s failed to run start-pre exectuable: %s", unit_id(UNIT(s)), strerror(-r));
034c6ed7
LP
574 socket_enter_dead(s, false);
575}
576
577static void socket_enter_running(Socket *s) {
578 int r;
579
580 assert(s);
581
87f0e418 582 if ((r = manager_add_job(UNIT(s)->meta.manager, JOB_START, UNIT(s->service), JOB_REPLACE, true, NULL)) < 0)
034c6ed7
LP
583 goto fail;
584
585 socket_set_state(s, SOCKET_RUNNING);
586 return;
587
588fail:
87f0e418 589 log_warning("%s failed to queue socket startup job: %s", unit_id(UNIT(s)), strerror(-r));
034c6ed7
LP
590 socket_enter_dead(s, false);
591}
592
593static void socket_run_next(Socket *s, bool success) {
594 int r;
595
596 assert(s);
597 assert(s->control_command);
598 assert(s->control_command->command_next);
599
600 if (!success)
601 s->failure = true;
602
603 s->control_command = s->control_command->command_next;
604
605 if ((r = socket_spawn(s, s->control_command, true, &s->control_pid)) < 0)
606 goto fail;
607
608 return;
609
610fail:
611 if (s->state == SOCKET_STOP_PRE)
612 socket_enter_stop_post(s, false);
613 else if (s->state == SOCKET_STOP_POST)
614 socket_enter_dead(s, false);
615 else
616 socket_enter_stop_pre(s, false);
617}
618
87f0e418
LP
619static int socket_start(Unit *u) {
620 Socket *s = SOCKET(u);
83c60c9f
LP
621
622 assert(s);
623
034c6ed7
LP
624 /* We cannot fulfill this request right now, try again later
625 * please! */
626 if (s->state == SOCKET_STOP_PRE ||
627 s->state == SOCKET_STOP_PRE_SIGKILL ||
628 s->state == SOCKET_STOP_PRE_SIGTERM ||
629 s->state == SOCKET_STOP_POST ||
630 s->state == SOCKET_STOP_POST_SIGTERM ||
631 s->state == SOCKET_STOP_POST_SIGKILL)
632 return -EAGAIN;
633
83c60c9f
LP
634 if (s->state == SOCKET_START_PRE ||
635 s->state == SOCKET_START_POST)
034c6ed7 636 return 0;
83c60c9f 637
034c6ed7 638 /* Cannot run this without the service being around */
87f0e418 639 if (s->service->meta.load_state != UNIT_LOADED)
034c6ed7 640 return -ENOENT;
83c60c9f 641
034c6ed7 642 assert(s->state == SOCKET_DEAD || s->state == SOCKET_MAINTAINANCE);
83c60c9f 643
034c6ed7
LP
644 s->failure = false;
645 socket_enter_start_pre(s);
646 return 0;
647}
83c60c9f 648
87f0e418
LP
649static int socket_stop(Unit *u) {
650 Socket *s = SOCKET(u);
034c6ed7
LP
651
652 assert(s);
653
654 /* We cannot fulfill this request right now, try again later
655 * please! */
656 if (s->state == SOCKET_START_PRE ||
657 s->state == SOCKET_START_POST)
658 return -EAGAIN;
83c60c9f 659
034c6ed7 660 assert(s->state == SOCKET_LISTENING || s->state == SOCKET_RUNNING);
83c60c9f 661
034c6ed7 662 socket_enter_stop_pre(s, true);
542563ba
LP
663 return 0;
664}
665
87f0e418
LP
666static UnitActiveState socket_active_state(Unit *u) {
667 assert(u);
5cb5a6ff 668
acbb0225 669 return state_translation_table[SOCKET(u)->state];
5cb5a6ff
LP
670}
671
acbb0225 672static void socket_fd_event(Unit *u, int fd, uint32_t events, Watch *w) {
87f0e418 673 Socket *s = SOCKET(u);
9152c765 674
034c6ed7 675 assert(s);
9152c765 676
e9af15c3 677 log_debug("Incoming traffic on %s", unit_id(u));
9152c765 678
f94ea366 679 if (events != EPOLLIN)
034c6ed7 680 socket_enter_stop_pre(s, false);
9152c765 681
034c6ed7 682 socket_enter_running(s);
9152c765
LP
683}
684
87f0e418
LP
685static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
686 Socket *s = SOCKET(u);
034c6ed7 687 bool success;
5cb5a6ff
LP
688
689 assert(s);
034c6ed7 690 assert(pid >= 0);
5cb5a6ff 691
bd982a8b 692 success = code == CLD_EXITED && status == 0;
034c6ed7 693 s->failure = s->failure || !success;
542563ba 694
034c6ed7
LP
695 assert(s->control_pid == pid);
696 assert(s->control_command);
697
698 exec_status_fill(&s->control_command->exec_status, pid, code, status);
699 s->control_pid = 0;
700
94f04347 701 log_debug("%s control process exited, code=%s status=%i", unit_id(u), sigchld_code_to_string(code), status);
034c6ed7
LP
702
703 if (s->control_command->command_next &&
acbb0225
LP
704 (success || (s->state == SOCKET_EXEC_STOP_PRE || s->state == SOCKET_EXEC_STOP_POST))) {
705 log_debug("%s running next command for the state %s", unit_id(u), state_string_table[s->state]);
034c6ed7 706 socket_run_next(s, success);
acbb0225 707 } else {
034c6ed7
LP
708 /* No further commands for this step, so let's figure
709 * out what to do next */
5cb5a6ff 710
bd982a8b 711 log_debug("%s got final SIGCHLD for state %s", unit_id(u), state_string_table[s->state]);
acbb0225 712
034c6ed7
LP
713 switch (s->state) {
714
715 case SOCKET_START_PRE:
716 if (success)
acbb0225 717 socket_enter_start_post(s);
034c6ed7
LP
718 else
719 socket_enter_stop_pre(s, false);
720 break;
721
722 case SOCKET_START_POST:
723 if (success)
e9af15c3 724 socket_enter_listening(s);
034c6ed7
LP
725 else
726 socket_enter_stop_pre(s, false);
727 break;
728
729 case SOCKET_STOP_PRE:
730 case SOCKET_STOP_PRE_SIGTERM:
731 case SOCKET_STOP_PRE_SIGKILL:
732 socket_enter_stop_post(s, success);
733 break;
734
735 case SOCKET_STOP_POST:
736 case SOCKET_STOP_POST_SIGTERM:
737 case SOCKET_STOP_POST_SIGKILL:
738 socket_enter_dead(s, success);
739 break;
740
741 default:
742 assert_not_reached("Uh, control process died at wrong time.");
743 }
744 }
745}
5cb5a6ff 746
acbb0225 747static void socket_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
87f0e418 748 Socket *s = SOCKET(u);
5cb5a6ff 749
034c6ed7
LP
750 assert(s);
751 assert(elapsed == 1);
752
acbb0225 753 assert(w == &s->timer_watch);
034c6ed7
LP
754
755 switch (s->state) {
756
757 case SOCKET_START_PRE:
758 case SOCKET_START_POST:
87f0e418 759 log_warning("%s operation timed out. Stopping.", unit_id(u));
034c6ed7
LP
760 socket_enter_stop_pre(s, false);
761 break;
762
763 case SOCKET_STOP_PRE:
87f0e418 764 log_warning("%s stopping timed out. Terminating.", unit_id(u));
034c6ed7
LP
765 socket_enter_signal(s, SOCKET_STOP_PRE_SIGTERM, false);
766 break;
767
768 case SOCKET_STOP_PRE_SIGTERM:
87f0e418 769 log_warning("%s stopping timed out. Killing.", unit_id(u));
034c6ed7
LP
770 socket_enter_signal(s, SOCKET_STOP_PRE_SIGKILL, false);
771 break;
772
773 case SOCKET_STOP_PRE_SIGKILL:
87f0e418 774 log_warning("%s still around after SIGKILL. Ignoring.", unit_id(u));
034c6ed7
LP
775 socket_enter_stop_post(s, false);
776 break;
777
778 case SOCKET_STOP_POST:
87f0e418 779 log_warning("%s stopping timed out (2). Terminating.", unit_id(u));
034c6ed7
LP
780 socket_enter_signal(s, SOCKET_STOP_POST_SIGTERM, false);
781 break;
782
783 case SOCKET_STOP_POST_SIGTERM:
87f0e418 784 log_warning("%s stopping timed out (2). Killing.", unit_id(u));
034c6ed7
LP
785 socket_enter_signal(s, SOCKET_STOP_POST_SIGKILL, false);
786 break;
787
788 case SOCKET_STOP_POST_SIGKILL:
87f0e418 789 log_warning("%s still around after SIGKILL (2). Entering maintainance mode.", unit_id(u));
034c6ed7
LP
790 socket_enter_dead(s, false);
791 break;
792
793 default:
794 assert_not_reached("Timeout at wrong time.");
795 }
5cb5a6ff
LP
796}
797
44d8db9e
LP
798int socket_collect_fds(Socket *s, int **fds, unsigned *n_fds) {
799 int *rfds;
800 unsigned rn_fds, k;
801 SocketPort *p;
802
803 assert(s);
804 assert(fds);
805 assert(n_fds);
806
807 /* Called from the service code for requesting our fds */
808
809 rn_fds = 0;
810 LIST_FOREACH(port, p, s->ports)
811 if (p->fd >= 0)
812 rn_fds++;
813
814 if (!(rfds = new(int, rn_fds)) < 0)
815 return -ENOMEM;
816
817 k = 0;
818 LIST_FOREACH(port, p, s->ports)
819 if (p->fd >= 0)
820 rfds[k++] = p->fd;
821
822 assert(k == rn_fds);
823
824 *fds = rfds;
825 *n_fds = rn_fds;
826
827 return 0;
828}
829
ceee3d82
LP
830void socket_notify_service_dead(Socket *s) {
831 assert(s);
832
833 /* The service is dead. Dang. */
834
835 if (s->state == SOCKET_RUNNING) {
836 log_debug("%s got notified about service death.", unit_id(UNIT(s)));
837 socket_enter_listening(s);
838 }
839}
840
87f0e418 841const UnitVTable socket_vtable = {
5cb5a6ff
LP
842 .suffix = ".socket",
843
034c6ed7
LP
844 .init = socket_init,
845 .done = socket_done,
846
5cb5a6ff
LP
847 .dump = socket_dump,
848
542563ba
LP
849 .start = socket_start,
850 .stop = socket_stop,
5cb5a6ff
LP
851
852 .active_state = socket_active_state,
853
9152c765 854 .fd_event = socket_fd_event,
034c6ed7
LP
855 .sigchld_event = socket_sigchld_event,
856 .timer_event = socket_timer_event
5cb5a6ff 857};