diff options
| -rw-r--r-- | README | 12 | ||||
| -rw-r--r-- | sami.3 | 14 | ||||
| -rw-r--r-- | sami.c | 91 | ||||
| -rw-r--r-- | sami.h | 7 |
4 files changed, 91 insertions, 33 deletions
diff --git a/README b/README index 1f0cb82..6cc1e88 100644 --- a/README +++ b/README @@ -7,25 +7,27 @@ SYNOPSIS #include <sami.h> int - SAMI_make(SAMI *actor, SAMI_Handler *handler, void *arg); + SAMI_make(SAMI *actor, SAMI_Handler *handler); int SAMI_send(SAMI *actor, void *buf, size_t length); int - SAMI_recv(void *buf, size_t length); - - int SAMI_kill(SAMI *actor); + SAMI * + SAMI_parent(void); + DESCRIPTION sami is a library for handling actors. It uses fork(2) for making actors, and unix(7) sockets for message delivering. RETURN VALUE - All functions return 0 on success, and any other number on failure. + Functions usually return 0 on success, and any other number on failure. Consider checking errno(7) in the latter case. + SAMI_parent() returns a valid pointer. + SEE ALSO fork(2), unix(7) diff --git a/sami.3 b/sami.3 index 371c682..ba6b63b 100644 --- a/sami.3 +++ b/sami.3 @@ -10,17 +10,17 @@ . .In sami.h .Ft "int" -.Fn SAMI_make "SAMI *actor" "SAMI_Handler *handler" "void *arg" +.Fn SAMI_make "SAMI *actor" "SAMI_Handler *handler" . .Ft "int" .Fn SAMI_send "SAMI *actor" "void *buf" "size_t length" . .Ft "int" -.Fn SAMI_recv "void *buf" "size_t length" -. -.Ft "int" .Fn SAMI_kill "SAMI *actor" . +.Ft "SAMI *" +.Fn SAMI_parent "void" +. .Sh DESCRIPTION .Nm is a library @@ -33,12 +33,16 @@ and sockets for message delivering. . .Sh RETURN VALUE -All functions return 0 on success, +Functions usually return 0 on success, and any other number on failure. Consider checking .Xr errno 7 in the latter case. . +.Pp +.Fn SAMI_parent +returns a valid pointer. +. .Sh SEE ALSO .Xr fork 2 , .Xr unix 7 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]; } diff --git a/sami.h b/sami.h index 53e5ad8..fdab71c 100644 --- a/sami.h +++ b/sami.h @@ -4,7 +4,6 @@ #include <stddef.h> #include <unistd.h> -extern int SAMI__fd; struct SAMI { @@ -13,11 +12,11 @@ struct SAMI }; typedef struct SAMI SAMI; -typedef void SAMI_Handler(void *arg); +typedef int SAMI_Handler(const SAMI *sender, void *message, size_t length); -int SAMI_make(SAMI *actor, SAMI_Handler *handler, void *arg); +int SAMI_make(SAMI *actor, SAMI_Handler *handler); int SAMI_send(SAMI *actor, void *buf, size_t length); -int SAMI_recv(void *buf, size_t length); int SAMI_kill(SAMI *actor); +SAMI *SAMI_parent(void); #endif /* __SAMI_H__ */ |