1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include <sys/socket.h>
18 lxc_log_define(sync
, lxc
);
20 bool sync_wait(int fd
, int sequence
)
25 ret
= lxc_read_nointr(fd
, &sync
, sizeof(sync
));
27 return log_error_errno(false, errno
, "Sync wait failure");
32 if ((size_t)ret
!= sizeof(sync
))
33 return log_error(false, "Unexpected sync size: %zu expected %zu", (size_t)ret
, sizeof(sync
));
35 if (sync
== SYNC_ERROR
)
36 return log_error(false, "An error occurred in another process (expected sequence number %d)", sequence
);
39 return log_error(false, "Invalid sequence number %d. Expected sequence number %d", sync
, sequence
);
44 bool sync_wake(int fd
, int sequence
)
48 if (lxc_write_nointr(fd
, &sync
, sizeof(sync
)) < 0)
49 return log_error_errno(false, errno
, "Sync wake failure");
54 static bool __sync_barrier(int fd
, int sequence
)
56 if (!sync_wake(fd
, sequence
))
59 return sync_wait(fd
, sequence
+ 1);
62 static inline const char *start_sync_to_string(int state
)
65 case START_SYNC_STARTUP
:
67 case START_SYNC_CONFIGURE
:
69 case START_SYNC_POST_CONFIGURE
:
70 return "post-configure";
71 case START_SYNC_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
:
79 case START_SYNC_RESTART
:
81 case START_SYNC_POST_RESTART
:
82 return "post-restart";
86 return "invalid sync state";
90 bool lxc_sync_barrier_parent(struct lxc_handler
*handler
, int sequence
)
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
);
97 bool lxc_sync_barrier_child(struct lxc_handler
*handler
, int sequence
)
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
);
104 bool lxc_sync_wake_parent(struct lxc_handler
*handler
, int sequence
)
106 TRACE("Child waking parent with sequence %s", start_sync_to_string(sequence
));
107 return sync_wake(handler
->sync_sock
[0], sequence
);
110 bool lxc_sync_wait_parent(struct lxc_handler
*handler
, int sequence
)
112 TRACE("Parent waiting for child with sequence %s", start_sync_to_string(sequence
));
113 return sync_wait(handler
->sync_sock
[0], sequence
);
116 bool lxc_sync_wait_child(struct lxc_handler
*handler
, int sequence
)
118 TRACE("Child waiting for parent with sequence %s", start_sync_to_string(sequence
));
119 return sync_wait(handler
->sync_sock
[1], sequence
);
122 bool lxc_sync_wake_child(struct lxc_handler
*handler
, int sequence
)
124 TRACE("Child waking parent with sequence %s", start_sync_to_string(sequence
));
125 return sync_wake(handler
->sync_sock
[1], sequence
);
128 bool lxc_sync_init(struct lxc_handler
*handler
)
132 ret
= socketpair(AF_LOCAL
, SOCK_STREAM
, 0, handler
->sync_sock
);
134 return log_error_errno(false, errno
, "failed to create synchronization socketpair");
136 /* Be sure we don't inherit this after the exec */
137 ret
= fcntl(handler
->sync_sock
[0], F_SETFD
, FD_CLOEXEC
);
139 return log_error_errno(false, errno
, "Failed to make socket close-on-exec");
141 TRACE("Initialized synchronization infrastructure");
145 void lxc_sync_fini_child(struct lxc_handler
*handler
)
147 close_prot_errno_disarm(handler
->sync_sock
[0]);
150 void lxc_sync_fini_parent(struct lxc_handler
*handler
)
152 close_prot_errno_disarm(handler
->sync_sock
[1]);
155 void lxc_sync_fini(struct lxc_handler
*handler
)
157 lxc_sync_fini_child(handler
);
158 lxc_sync_fini_parent(handler
);