diff options
Diffstat (limited to 'sami.c')
| -rw-r--r-- | sami.c | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/sami.c b/sami.c index 6c8d42b..69f0796 100644 --- a/sami.c +++ b/sami.c @@ -3,17 +3,42 @@ #include <errno.h> #include <signal.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys/wait.h> +#include <sys/types.h> +#include <sys/poll.h> -int SAMI__fd; +#define ACTORS_MAX 1024 +#define MESSAGE_LENGTH_MAX 65536 -int SAMI_make(SAMI *actor, SAMI_Handler *handler, void *arg) +static struct pollfd pfd[ACTORS_MAX]; +static SAMI actors[ACTORS_MAX]; +char buffer[MESSAGE_LENGTH_MAX]; +static int self_fd; + +static ssize_t findspace(void) { - int pair[2]; + size_t i; + + for (i = 1; i < ACTORS_MAX; ++i) + if (pfd[i].fd == -1) + return i; + + return -1; +} + +int SAMI_make(SAMI *actor, SAMI_Handler *handler) +{ + int pair[2], res; + ssize_t i, sz; + + i = findspace(); + if (i == -1) + return 1; if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) == -1) return 1; @@ -21,11 +46,47 @@ int SAMI_make(SAMI *actor, SAMI_Handler *handler, void *arg) if (!(actor->pid = fork())) { - SAMI__fd = pair[1]; - handler(arg); + close(pair[0]); + actors[0].fd = pfd[0].fd = self_fd; + self_fd = pair[1]; + actors[0].pid = -1; + + for (i = 1; i < ACTORS_MAX; ++i) + actors[i].fd = -1, + pfd[i].fd = -1, + pfd[i].events = POLLIN; +retry: + waitpid(-1, 0, WNOHANG); + res = poll(pfd, ACTORS_MAX, 0); + if (res == -1) + if (errno = EINTR) + goto retry; + else /* TODO: log fail */ + exit(1); + else if (res == 0) + goto retry; + + for (i = 0; i < ACTORS_MAX; ++i) + { + if (!(pfd[i].revents & POLLIN)) + break; + + sz = recv(pfd[i].fd, buffer, sizeof(buffer), 0); + /* TODO: log if sz == -1 */ + if (handler(&actor[i], buffer, sz)) + goto end; + } + goto retry; +end: exit(0); } + close(pair[1]); + if (actor->pid == -1) + close(pair[0]); + else + memcpy(&actors[i], actor, sizeof(*actor)); + return actor->pid == -1; } @@ -34,24 +95,16 @@ int SAMI_send(SAMI *actor, void *buf, size_t length) return send(actor->fd, buf, length, 0) == -1; } -int SAMI_recv(void *buf, size_t length) -{ - return recvfrom(SAMI__fd, buf, length, 0, 0, 0) == -1; -} - int SAMI_kill(SAMI *actor) { int res; - if (kill(actor->pid, SIGKILL)) + if (actor->pid == -1 + || kill(actor->pid, SIGKILL)) return 1; +} - for (;;) - if (waitpid(actor->pid, 0, 0) == -1) - if (errno == EINTR) - continue; - else - return 1; - else - return 0; +SAMI *SAMI_parent(void) +{ + return &actors[0]; } |