ref: 11bcdbc521b17d7104d5118806c3891092b6979d
parent: 7b9f83e03f011c5c384e066214a81544d296c157
author: zamfofex <zamfofex@twdb.moe>
date: Mon Jun 24 19:36:14 EDT 2024
add daemon to spawn processes (to avoid leaking resources)
--- a/tools/analyse.c
+++ b/tools/analyse.c
@@ -572,6 +572,8 @@
char *value;
char **options;
+ moonfish_spawner(argv[0]);
+
command = moonfish_args(args, format, argc, argv);
command_count = argc - (command - argv);
if (command_count < 1) moonfish_usage(args, format, argv[0]);
@@ -646,7 +648,7 @@
fancy->x = 0;
fancy->y = 0;
- moonfish_spawn(argv[0], command, &fancy->in, &fancy->out, NULL);
+ moonfish_spawn(command, &fancy->in, &fancy->out, NULL);
fancy->i = 0;
fancy->count = 1;
--- a/tools/battle.c
+++ b/tools/battle.c
@@ -183,7 +183,7 @@
if (*command != NULL && !strcmp(*command, "--"))
command++;
- moonfish_spawn(argv0, command, &bot->in, &bot->out, NULL);
+ moonfish_spawn(command, &bot->in, &bot->out, NULL);
if (bot->ugi) fprintf(bot->in, "ugi\n");
else fprintf(bot->in, "uci\n");
@@ -441,7 +441,9 @@
char *argv0;
- if (argc < 1) return 1;
+ (void) argc;
+
+ moonfish_spawner(argv[0]);
battle.fen = NULL;
--- a/tools/book.c
+++ b/tools/book.c
@@ -60,6 +60,8 @@
int error;
pthread_t thread;
+ moonfish_spawner(argv[0]);
+
command = moonfish_args(args, format, argc, argv);
if (args[0].value == NULL) moonfish_usage(args, format, argv[0]);
@@ -134,7 +136,7 @@
if (i == 0) fprintf(stderr, "%s: Empty book.\n", argv[0]);
- moonfish_spawn(argv[0], command, &in, &out, NULL);
+ moonfish_spawn(command, &in, &out, NULL);
error = pthread_create(&thread, NULL, moonfish_book_start, out);
if (error != 0)
--- a/tools/chat.c
+++ b/tools/chat.c
@@ -174,7 +174,7 @@
moonfish_chess(&chess);
- moonfish_spawn(argv0, command, &in, &out, NULL);
+ moonfish_spawn(command, &in, &out, NULL);
fprintf(in, "uci\n");
moonfish_wait(out, "uciok");
@@ -352,6 +352,8 @@
};
char **options, **command;
+
+ moonfish_spawner(argv[0]);
/* todo: validate nickname & channels*/
options = moonfish_args(args, format, argc, argv);
--- a/tools/lichess.c
+++ b/tools/lichess.c
@@ -274,7 +274,7 @@
game = data;
- moonfish_spawn(game->argv0, game->argv, &in, &out, NULL);
+ moonfish_spawn(game->argv, &in, &out, NULL);
tls = moonfish_connect(game->argv0, game->host, game->port);
snprintf(request, sizeof request, "GET /api/bot/game/stream/%s", game->id);
@@ -505,6 +505,8 @@
int command_count;
struct tls *tls;
char *username;
+
+ moonfish_spawner(argv[0]);
command = moonfish_args(args, format, argc, argv);
command_count = argc - (command - argv);
--- a/tools/play.c
+++ b/tools/play.c
@@ -319,6 +319,8 @@
char **command;
int command_count;
+ moonfish_spawner(argv[0]);
+
command = moonfish_args(args, format, argc, argv);
command_count = argc - (command - argv);
if (command_count < 1) moonfish_usage(args, format, argv[0]);
@@ -325,7 +327,7 @@
name = names;
- moonfish_spawn(argv[0], command, &in, &out, NULL);
+ moonfish_spawn(command, &in, &out, NULL);
if (tcgetattr(0, &moonfish_termios))
{--- a/tools/tools.h
+++ b/tools/tools.h
@@ -15,7 +15,9 @@
char *description;
};
-void moonfish_spawn(char *argv0, char **argv, FILE **in, FILE **out, char *directory);
+void moonfish_spawner(char *argv0);
+void moonfish_spawn(char **argv, FILE **in, FILE **out, char *directory);
+
char *moonfish_next(FILE *file);
char *moonfish_wait(FILE *file, char *name);
char **moonfish_args(struct moonfish_arg *args, char *rest_format, int argc, char **argv);
--- a/tools/ugi.c
+++ b/tools/ugi.c
@@ -44,7 +44,8 @@
void *(*start1)(void *data);
void *(*start2)(void *data);
- moonfish_spawn(argv0, argv, &in, &out, NULL);
+ moonfish_spawner(argv0);
+ moonfish_spawn(argv, &in, &out, NULL);
for (;;)
{--- a/tools/utils.c
+++ b/tools/utils.c
@@ -6,87 +6,417 @@
#include <string.h>
#include <errno.h>
#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <pthread.h>
+#include <sys/un.h>
#include "tools.h"
-static int moonfish_fork(char *argv0, char **argv, int *in_fd, int *out_fd, char *directory)
+static pid_t moonfish_spawner_pid;
+static char *moonfish_spawner_argv0;
+static int moonfish_spawner_fd;
+static char *moonfish_spawner_dir_name;
+static char *moonfish_spawner_socket_name;
+
+static void *moonfish_read_pipe(void *data)
{- int p1[2], p2[2];
- int pid;
+ char ch;
+ int *fds;
+ fds = data;
+ while (read(fds[0], &ch, 1) > 0) { }+ if (moonfish_spawner_socket_name != NULL)
+ {+ if (unlink(moonfish_spawner_socket_name) != 0)
+ perror(moonfish_spawner_argv0);
+ }
+ if (moonfish_spawner_dir_name != NULL)
+ {+ if (rmdir(moonfish_spawner_dir_name) != 0)
+ perror(moonfish_spawner_argv0);
+ }
+ exit(0);
+}
+
+void moonfish_spawner(char *argv0)
+{+ int fd;
+ FILE *in, *out;
+ pid_t pid;
+ int i, count, length;
+ char **argv;
+ char *directory;
+ struct sigaction action;
+ pthread_t thread;
+ int fds[2];
+ struct sockaddr_un address = {0};- if (pipe(p1) < 0) return 1;
- if (pipe(p2) < 0) return 1;
+ moonfish_spawner_argv0 = argv0;
- pid = fork();
- if (pid < 0) return 1;
+ moonfish_spawner_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (moonfish_spawner_fd < 0)
+ {+ perror(argv0);
+ exit(1);
+ }
- if (pid)
+ if (pipe(fds) != 0)
{- *in_fd = p1[1];
- *out_fd = p2[0];
- close(p1[0]);
- close(p2[1]);
- return 0;
+ perror(argv0);
+ exit(1);
}
- if (directory != NULL)
+ moonfish_spawner_pid = fork();
+ if (moonfish_spawner_pid < 0)
{- if (chdir(directory))
+ perror(argv0);
+ exit(1);
+ }
+
+ if (moonfish_spawner_pid != 0)
+ return;
+
+ close(fds[1]);
+
+ pthread_create(&thread, NULL, &moonfish_read_pipe, fds);
+
+ action.sa_flags = SA_NOCLDWAIT;
+ action.sa_handler = SIG_DFL;
+ if (sigemptyset(&action.sa_mask))
+ {+ perror(argv0);
+ exit(1);
+ }
+ if (sigaction(SIGCHLD, &action, NULL))
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ address.sun_family = AF_UNIX;
+ strcpy(address.sun_path, "/tmp/moon-XXXXXX");
+
+ if (mkdtemp(address.sun_path) == NULL)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ moonfish_spawner_dir_name = strdup(address.sun_path);
+ if (moonfish_spawner_dir_name == NULL)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ strcat(address.sun_path, "/socket");
+
+ moonfish_spawner_socket_name = strdup(address.sun_path);
+ if (moonfish_spawner_socket_name == NULL)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (bind(moonfish_spawner_fd, (void *) &address, sizeof address) != 0)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (listen(moonfish_spawner_fd, 8) < 0)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ for (;;)
+ {+ fd = accept(moonfish_spawner_fd, NULL, NULL);
+ if (fd < 0)
{perror(argv0);
exit(1);
}
+
+ pid = fork();
+ if (pid < 0)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (pid == 0) break;
+ close(fd);
}
- dup2(p1[0], 0);
- dup2(p2[1], 1);
- dup2(p2[1], 2);
+ close(fds[0]);
+ close(moonfish_spawner_fd);
- close(p1[0]);
- close(p1[1]);
- close(p2[0]);
- close(p2[1]);
+ in = fdopen(fd, "r");
+ if (in == NULL)
+ {+ perror(argv0);
+ exit(1);
+ }
+ out = fdopen(fd, "w");
+ if (out == NULL)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (setvbuf(in, NULL, _IONBF, 0) != 0)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (setvbuf(out, NULL, _IONBF, 0) != 0)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ pid = getpid();
+ if (fwrite(&pid, sizeof pid, 1, out) != 1)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (fread(&length, sizeof length, 1, in) != 1)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (length < 0)
+ {+ fprintf(stderr, "%s: invalid length\n", argv0);
+ exit(1);
+ }
+
+ if (length > 0)
+ {+ directory = malloc(length + 1);
+ if (directory == NULL)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ directory[length] = 0;
+
+ if (fread(directory, length, 1, in) != 1)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (chdir(directory) != 0)
+ {+ perror(argv0);
+ exit(1);
+ }
+ }
+
+ if (fread(&count, sizeof count, 1, in) != 1)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (count < 1)
+ {+ fprintf(stderr, "%s: too few arguments\n", argv0);
+ exit(1);
+ }
+
+ argv = malloc(sizeof *argv * (count + 1));
+ if (argv == NULL)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ argv[count] = NULL;
+
+ for (i = 0 ; i < count ; i++)
+ {+ if (fread(&length, sizeof length, 1, in) != 1)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ argv[i] = malloc(length + 1);
+ if (argv[i] == NULL)
+ {+ perror(argv0);
+ exit(1);
+ }
+ argv[i][length] = 0;
+
+ if (fread(argv[i], length, 1, in) != 1)
+ {+ perror(argv0);
+ exit(1);
+ }
+ }
+
+ if (dup2(fd, 0) < 0 || dup2(fd, 1) < 0)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ close(fd);
+
+ fd = open("/dev/null", O_WRONLY);+ if (fd < 0)
+ {+ perror(argv0);
+ exit(1);
+ }
+
+ if (dup2(fd, 2) < 0)
+ {+ perror(argv0);
+ exit(1);
+ }
+
execvp(argv[0], argv);
fprintf(stderr, "%s: %s: %s\n", argv0, argv[0], strerror(errno));
exit(1);
}
-void moonfish_spawn(char *argv0, char **argv, FILE **in, FILE **out, char *directory)
+void moonfish_spawn(char **argv, FILE **in, FILE **out, char *directory)
{- int in_fd, out_fd;
+ pid_t pid;
+ int fd;
+ int i, count;
+ struct sockaddr_un address;
+ socklen_t length;
- if (moonfish_fork(argv0, argv, &in_fd, &out_fd, directory))
+ pid = waitpid(moonfish_spawner_pid, NULL, WNOHANG);
+ if (pid < 0)
{- perror(argv0);
+ perror(moonfish_spawner_argv0);
exit(1);
}
+ if (pid != 0)
+ {+ fprintf(stderr, "%s: spawner exited\n", moonfish_spawner_argv0);
+ exit(1);
+ }
- *in = fdopen(in_fd, "w");
+ length = sizeof address;
+ if (getsockname(moonfish_spawner_fd, (void *) &address, &length) != 0)
+ {+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0)
+ {+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+
+ if (connect(fd, (void *) &address, length) != 0)
+ {+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+
+ *in = fdopen(dup(fd), "w");
if (*in == NULL)
{- perror(argv0);
+ perror(moonfish_spawner_argv0);
exit(1);
}
- *out = fdopen(out_fd, "r");
+ *out = fdopen(dup(fd), "r");
if (*out == NULL)
{- perror(argv0);
+ perror(moonfish_spawner_argv0);
exit(1);
}
- errno = 0;
- if (setvbuf(*in, NULL, _IOLBF, 0))
+ close(fd);
+
+ if (setvbuf(*in, NULL, _IONBF, 0) != 0)
{- if (errno) perror(argv0);
+ perror(moonfish_spawner_argv0);
exit(1);
}
- errno = 0;
- if (setvbuf(*out, NULL, _IOLBF, 0))
+ if (setvbuf(*out, NULL, _IONBF, 0) != 0)
{- if (errno) perror(argv0);
+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+
+ if (directory == NULL) directory = "";
+ count = strlen(directory);
+ if (fwrite(&count, sizeof count, 1, *in) != 1)
+ {+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+
+ if (fwrite(directory, count, 1, *in) != 1)
+ {+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+
+ count = 0;
+ while (argv[count] != NULL)
+ count++;
+
+ if (fwrite(&count, sizeof count, 1, *in) != 1)
+ {+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+
+ for (i = 0 ; argv[i] != NULL ; i++)
+ {+ count = strlen(argv[i]);
+ if (fwrite(&count, sizeof count, 1, *in) != 1)
+ {+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+
+ if (fwrite(argv[i], count, 1, *in) != 1)
+ {+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+ }
+
+ if (fread(&pid, sizeof pid, 1, *out) != 1)
+ {+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+
+ if (setvbuf(*in, NULL, _IOLBF, 0) != 0)
+ {+ perror(moonfish_spawner_argv0);
+ exit(1);
+ }
+
+ if (setvbuf(*out, NULL, _IOLBF, 0) != 0)
+ {+ perror(moonfish_spawner_argv0);
exit(1);
}
}
--
⑨