From 05882b74cf9d8a20cdf8cb4e66f5cdf09776d93c Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 9 Jul 2022 14:19:52 +0100 Subject: [PATCH] prefork-interp: wip Signed-off-by: Ian Jackson --- prefork-interp.c | 53 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/prefork-interp.c b/prefork-interp.c index 0921835..3b77f61 100644 --- a/prefork-interp.c +++ b/prefork-interp.c @@ -6,6 +6,7 @@ /* * Process structure: * client (C wrapper) connects to server + * (including reading ack byte) * if fails or garbage * === acquire lock === * makes new listening socket @@ -53,6 +54,7 @@ * * monitor [fd0: null, fd[12]: syslgo] * other fds: call(server-end) + * sends ack byte * receives args, env, fds * forks executor * @@ -78,23 +80,60 @@ struct sockaddr_un sun; -int main(int argc, const char *const *argv) { - script = process_opts(argc, argv); +#define ACK_BYTE '\n' + +// Returns: call(client-end) fd, or -1 to mean "is garbage" +// find_socket_path must have been called +static int attempt_connect_existing(void) { + int r; + int fd = -1; - find_socket_path(); FILLZERO(sun); sun.sun_family = AF_UNIX; assert(strlen(socket_path) <= sizeof(sun.sun_path)); strncpy(sun.sun_path, socket_path, sizeof(sun.sun_path)); bool isgarbage = check_garbage(); + if (isgarbage) goto x_garbage; - int client_fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (client_fd==-1) diee("socket() for client"); + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd==-1) diee("socket() for client"); salen_t salen = sizeof(sun); r = connect(client, (const struct sockaddr*)sun, salen); if (r==-1) { - if (errno==ECONNREFUSED || errno==ENOENT) { - + if (errno==ECONNREFUSED || errno==ENOENT) goto x_garbgae; + diee("connect() %s", socket_path); + } + + for (;;) { + char ack; + sr = read(fd, &ack, 1); + if (sr == -1) { + if (errno==ECONNRESET) goto x_garbage; + if (errno==EINTR) continue; + diee("read() ack byte"); + } + if (sr == 0) { goto x_garbage; } + if (ack != '\n') die("got ack byte 0x%02x, not '\n'", ack); + return fd; + } + + x_garbage: + if (fd >= 0) close(fd); + return -1; +} + +static int connect_or_spawn(void) { + int fd = connect_existing(); + if (fd >= 0) return fd; + + let acquire_lock(); + fd = connect_existing(); + +int main(int argc, const char *const *argv) { + script = process_opts(argc, argv); + + find_socket_path(); + int fd = connect_or_spawn(); } -- 2.30.2