]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/sync.c
cgroups: use zalloc
[mirror_lxc.git] / src / lxc / sync.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE 1
5 #endif
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <sys/socket.h>
9 #include <sys/types.h>
10 #include <unistd.h>
11
12 #include "config.h"
13 #include "log.h"
14 #include "start.h"
15 #include "sync.h"
16 #include "utils.h"
17
18 lxc_log_define(sync, lxc);
19
20 bool sync_wait(int fd, int sequence)
21 {
22 int sync = -1;
23 ssize_t ret;
24
25 ret = lxc_read_nointr(fd, &sync, sizeof(sync));
26 if (ret < 0)
27 return log_error_errno(false, errno, "Sync wait failure");
28
29 if (!ret)
30 return true;
31
32 if ((size_t)ret != sizeof(sync))
33 return log_error(false, "Unexpected sync size: %zu expected %zu", (size_t)ret, sizeof(sync));
34
35 if (sync == SYNC_ERROR)
36 return log_error(false, "An error occurred in another process (expected sequence number %d)", sequence);
37
38 if (sync != sequence)
39 return log_error(false, "Invalid sequence number %d. Expected sequence number %d", sync, sequence);
40
41 return true;
42 }
43
44 bool sync_wake(int fd, int sequence)
45 {
46 int sync = sequence;
47
48 if (lxc_write_nointr(fd, &sync, sizeof(sync)) < 0)
49 return log_error_errno(false, errno, "Sync wake failure");
50
51 return true;
52 }
53
54 static bool __sync_barrier(int fd, int sequence)
55 {
56 if (!sync_wake(fd, sequence))
57 return false;
58
59 return sync_wait(fd, sequence + 1);
60 }
61
62 static inline const char *start_sync_to_string(int state)
63 {
64 switch (state) {
65 case START_SYNC_STARTUP:
66 return "startup";
67 case START_SYNC_CONFIGURE:
68 return "configure";
69 case START_SYNC_POST_CONFIGURE:
70 return "post-configure";
71 case START_SYNC_CGROUP:
72 return "cgroup";
73 case START_SYNC_CGROUP_UNSHARE:
74 return "cgroup-unshare";
75 case START_SYNC_CGROUP_LIMITS:
76 return "cgroup-limits";
77 case START_SYNC_READY_START:
78 return "ready-start";
79 case START_SYNC_RESTART:
80 return "restart";
81 case START_SYNC_POST_RESTART:
82 return "post-restart";
83 case SYNC_ERROR:
84 return "error";
85 default:
86 return "invalid sync state";
87 }
88 }
89
90 bool lxc_sync_barrier_parent(struct lxc_handler *handler, int sequence)
91 {
92 TRACE("Child waking parent with sequence %s and waiting for sequence %s",
93 start_sync_to_string(sequence), start_sync_to_string(sequence + 1));
94 return __sync_barrier(handler->sync_sock[0], sequence);
95 }
96
97 bool lxc_sync_barrier_child(struct lxc_handler *handler, int sequence)
98 {
99 TRACE("Parent waking child with sequence %s and waiting with sequence %s",
100 start_sync_to_string(sequence), start_sync_to_string(sequence + 1));
101 return __sync_barrier(handler->sync_sock[1], sequence);
102 }
103
104 bool lxc_sync_wake_parent(struct lxc_handler *handler, int sequence)
105 {
106 TRACE("Child waking parent with sequence %s", start_sync_to_string(sequence));
107 return sync_wake(handler->sync_sock[0], sequence);
108 }
109
110 bool lxc_sync_wait_parent(struct lxc_handler *handler, int sequence)
111 {
112 TRACE("Parent waiting for child with sequence %s", start_sync_to_string(sequence));
113 return sync_wait(handler->sync_sock[0], sequence);
114 }
115
116 bool lxc_sync_wait_child(struct lxc_handler *handler, int sequence)
117 {
118 TRACE("Child waiting for parent with sequence %s", start_sync_to_string(sequence));
119 return sync_wait(handler->sync_sock[1], sequence);
120 }
121
122 bool lxc_sync_wake_child(struct lxc_handler *handler, int sequence)
123 {
124 TRACE("Child waking parent with sequence %s", start_sync_to_string(sequence));
125 return sync_wake(handler->sync_sock[1], sequence);
126 }
127
128 bool lxc_sync_init(struct lxc_handler *handler)
129 {
130 int ret;
131
132 ret = socketpair(AF_LOCAL, SOCK_STREAM, 0, handler->sync_sock);
133 if (ret)
134 return log_error_errno(false, errno, "failed to create synchronization socketpair");
135
136 /* Be sure we don't inherit this after the exec */
137 ret = fcntl(handler->sync_sock[0], F_SETFD, FD_CLOEXEC);
138 if (ret < 0)
139 return log_error_errno(false, errno, "Failed to make socket close-on-exec");
140
141 TRACE("Initialized synchronization infrastructure");
142 return true;
143 }
144
145 void lxc_sync_fini_child(struct lxc_handler *handler)
146 {
147 close_prot_errno_disarm(handler->sync_sock[0]);
148 }
149
150 void lxc_sync_fini_parent(struct lxc_handler *handler)
151 {
152 close_prot_errno_disarm(handler->sync_sock[1]);
153 }
154
155 void lxc_sync_fini(struct lxc_handler *handler)
156 {
157 lxc_sync_fini_child(handler);
158 lxc_sync_fini_parent(handler);
159 }