rktio: processes
This commit is contained in:
parent
6c2f71bf80
commit
9e68886b26
|
@ -13,6 +13,8 @@ OBJS = rktio_filesystem.o \
|
|||
rktio_poll_set.o \
|
||||
rktio_ltps.o \
|
||||
rktio_network.o \
|
||||
rktio_process.o \
|
||||
rktio_envvars.o \
|
||||
rktio_error.o \
|
||||
rktio_main.o
|
||||
|
||||
|
@ -42,6 +44,12 @@ rktio_ltps.o: $(srcdir)/rktio_ltps.c $(RKTIO_HEADERS)
|
|||
rktio_network.o: $(srcdir)/rktio_network.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_network.o -c $(srcdir)/rktio_network.c
|
||||
|
||||
rktio_process.o: $(srcdir)/rktio_process.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_process.o -c $(srcdir)/rktio_process.c
|
||||
|
||||
rktio_envvars.o: $(srcdir)/rktio_envvars.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_envvars.o -c $(srcdir)/rktio_envvars.c
|
||||
|
||||
rktio_error.o: $(srcdir)/rktio_error.c $(RKTIO_HEADERS)
|
||||
$(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_error.o -c $(srcdir)/rktio_error.c
|
||||
|
||||
|
|
|
@ -9,8 +9,9 @@ The library is meant to be
|
|||
* always non-blocking;
|
||||
|
||||
* independent of global state (except on Windows, where internal
|
||||
global state is managed appropriately with locks), so that it works
|
||||
with or without threads; and
|
||||
global state is managed appropriately with locks, and except for
|
||||
Unix process handling without pthreads), so that it works with or
|
||||
without threads; and
|
||||
|
||||
* easily callable though a FFI.
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
static void do_check_valid(rktio_t *rktio, int ok, int where)
|
||||
{
|
||||
/* Beware that a reported error is nonsense if the failure
|
||||
was an unexpected result insteda of an error result. */
|
||||
if (!ok) {
|
||||
printf("error at %d: %d@%d = %s\n",
|
||||
where,
|
||||
|
@ -190,13 +192,12 @@ static void wait_read(rktio_t *rktio, rktio_fd_t *fd)
|
|||
rktio_poll_set_close(rktio, ps);
|
||||
}
|
||||
|
||||
static void check_read_write_pair(rktio_t *rktio, rktio_fd_t *fd, rktio_fd_t *fd2)
|
||||
static void check_read_write_pair(rktio_t *rktio, rktio_fd_t *fd, rktio_fd_t *fd2, int immediate_available)
|
||||
{
|
||||
rktio_ltps_t *lt;
|
||||
rktio_ltps_handle_t *h1, *h2;
|
||||
intptr_t amt, i;
|
||||
char buffer[256];
|
||||
int immediate_available = (!rktio_fd_is_socket(rktio, fd) && !rktio_fd_is_socket(rktio, fd2));
|
||||
|
||||
lt = try_check_ltps(rktio, fd, fd2, &h1, &h2);
|
||||
/* We expect `lt` to work everywhere exception Windows and with kqueue on non-sockets: */
|
||||
|
@ -566,7 +567,7 @@ int main()
|
|||
check_valid(fd2);
|
||||
check_valid(!rktio_poll_read_ready(rktio, fd));
|
||||
|
||||
check_read_write_pair(rktio, fd, fd2);
|
||||
check_read_write_pair(rktio, fd, fd2, 1);
|
||||
|
||||
/* Open pipe ends again: */
|
||||
fd2 = rktio_open(rktio, "demo_fifo", RKTIO_OPEN_WRITE | RKTIO_OPEN_CAN_EXIST);
|
||||
|
@ -637,7 +638,7 @@ int main()
|
|||
free(strs);
|
||||
}
|
||||
|
||||
check_read_write_pair(rktio, fd, fd2);
|
||||
check_read_write_pair(rktio, fd, fd2, 0);
|
||||
|
||||
fd = connect_loop(rktio, addr, NULL);
|
||||
rktio_free_addrinfo(rktio, addr);
|
||||
|
@ -675,7 +676,7 @@ int main()
|
|||
check_valid(addr);
|
||||
check_valid(rktio_udp_connect(rktio, fd2, addr));
|
||||
|
||||
check_read_write_pair(rktio, fd, fd2);
|
||||
check_read_write_pair(rktio, fd, fd2, 0);
|
||||
|
||||
/* Again, this time to fill & drain: */
|
||||
|
||||
|
@ -701,6 +702,51 @@ int main()
|
|||
check_valid(rktio_close(rktio, fd));
|
||||
check_valid(rktio_close(rktio, fd2));
|
||||
}
|
||||
|
||||
/* Processes */
|
||||
{
|
||||
rktio_status_t *status;
|
||||
rktio_process_result_t *result;
|
||||
char *argv[2] = { "/bin/cat", NULL };
|
||||
rktio_envvars_t *envvars = NULL;
|
||||
rktio_fd_t *err_fd = rktio_system_fd(rktio, 2, RKTIO_OPEN_WRITE);
|
||||
int done;
|
||||
|
||||
result = rktio_process(rktio, "/bin/cat", 1, argv,
|
||||
NULL, NULL, err_fd,
|
||||
rktio_get_current_directory(rktio), envvars,
|
||||
0,
|
||||
NULL);
|
||||
check_valid(result);
|
||||
|
||||
status = rktio_process_status(rktio, result->process);
|
||||
check_valid(status);
|
||||
check_valid(status->running);
|
||||
check_valid(!result->stderr_fd);
|
||||
free(status);
|
||||
|
||||
check_valid(!rktio_poll_subprocess_done(rktio, result->process));
|
||||
|
||||
check_read_write_pair(rktio, result->stdout_fd, result->stdin_fd, 0);
|
||||
|
||||
check_valid(rktio_poll_subprocess_done(rktio, result->process) != RKTIO_PROCESS_ERROR);
|
||||
|
||||
do {
|
||||
rktio_poll_set_t *ps;
|
||||
ps = rktio_make_poll_set(rktio);
|
||||
check_valid(ps);
|
||||
rktio_poll_add_process(rktio, result->process, ps);
|
||||
rktio_sleep(rktio, 0, ps, NULL);
|
||||
rktio_poll_set_close(rktio, ps);
|
||||
done = rktio_poll_subprocess_done(rktio, result->process);
|
||||
check_valid(done != RKTIO_PROCESS_ERROR);
|
||||
} while (!done);
|
||||
|
||||
rktio_process_forget(rktio, result->process);
|
||||
free(result);
|
||||
|
||||
check_valid(rktio_close(rktio, err_fd));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ void rktio_forget(rktio_t *rktio, rktio_fd_t *fd);
|
|||
#define RKTIO_WRITE_ERROR (-2)
|
||||
#define RKTIO_POLL_ERROR (-2)
|
||||
#define RKTIO_POLL_READY 1
|
||||
#define RKTIO_PROP_ERROR (-2)
|
||||
|
||||
intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||
intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len);
|
||||
|
@ -110,6 +109,8 @@ typedef struct rktio_length_and_addrinfo_t {
|
|||
|
||||
rktio_length_and_addrinfo_t *rktio_udp_recvfrom(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len);
|
||||
|
||||
#define RKTIO_PROP_ERROR (-2)
|
||||
|
||||
/* The following accessors return RKTIO_PROP_ERROR on failure */
|
||||
int rktio_udp_get_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd);
|
||||
int rktio_udp_set_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd, int on);
|
||||
|
@ -133,6 +134,51 @@ int rktio_udp_change_multicast_group(rktio_t *rktio, rktio_fd_t *rfd,
|
|||
rktio_addrinfo_t *intf_addr,
|
||||
int action);
|
||||
|
||||
/*************************************************/
|
||||
/* Environment variables */
|
||||
|
||||
typedef struct rktio_envvars_t rktio_envvars_t;
|
||||
|
||||
/*************************************************/
|
||||
/* Processes */
|
||||
|
||||
typedef struct rktio_process_t rktio_process_t;
|
||||
|
||||
#define RKTIO_PROCESS_NEW_GROUP (1<<0)
|
||||
#define RKTIO_PROCESS_STDOUT_AS_STDERR (1<<1)
|
||||
#define RKTIO_PROCESS_WINDOWS_EXACT_CMDLINE (1<<2)
|
||||
#define RKTIO_PROCESS_WINDOWS_CHAIN_TERMINATION (1<<3)
|
||||
|
||||
typedef struct rktio_process_result_t {
|
||||
rktio_process_t *process;
|
||||
rktio_fd_t *stdin_fd, *stdout_fd, *stderr_fd;
|
||||
} rktio_process_result_t;
|
||||
|
||||
rktio_process_result_t *rktio_process(rktio_t *rktio,
|
||||
const char *command, int argc, char **argv,
|
||||
rktio_fd_t *stdout_fd, rktio_fd_t *stdin_fd, rktio_fd_t *stderr_fd,
|
||||
const char *current_directory, rktio_envvars_t *envvars,
|
||||
int flags,
|
||||
void (*unix_child_process_callback)());
|
||||
|
||||
int rktio_process_kill(rktio_t *rktio, rktio_process_t *sp);
|
||||
int rktio_process_interrupt(rktio_t *rktio, rktio_process_t *sp);
|
||||
void rktio_process_forget(rktio_t *rktio, rktio_process_t *sp);
|
||||
|
||||
#define RKTIO_PROCESS_ERROR (-2)
|
||||
#define RKTIO_PROCESS_DONE 1
|
||||
|
||||
int rktio_poll_subprocess_done(rktio_t *rktio, rktio_process_t *sp);
|
||||
|
||||
typedef struct rktio_status_t {
|
||||
int running;
|
||||
int result;
|
||||
} rktio_status_t;
|
||||
|
||||
rktio_status_t *rktio_process_status(rktio_t *rktio, rktio_process_t *sp);
|
||||
|
||||
void rktio_block_child_signals(rktio_t*rktio, int block);
|
||||
|
||||
/*************************************************/
|
||||
/* File-descriptor sets for polling */
|
||||
|
||||
|
@ -151,12 +197,13 @@ void rktio_poll_add(rktio_t *rktio, rktio_fd_t *rfd, rktio_poll_set_t *fds, int
|
|||
void rktio_poll_add_receive(rktio_t *rktio, rktio_listener_t *listener, rktio_poll_set_t *fds);
|
||||
void rktio_poll_add_connect(rktio_t *rktio, rktio_connect_t *conn, rktio_poll_set_t *fds);
|
||||
void rktio_poll_add_addrinfo_lookup(rktio_t *rktio, rktio_addrinfo_lookup_t *lookup, rktio_poll_set_t *fds);
|
||||
void rktio_poll_add_process(rktio_t *rktio, rktio_process_t *sp, rktio_poll_set_t *fds);
|
||||
|
||||
void rktio_poll_set_add_nosleep(rktio_t *rktio, rktio_poll_set_t *fds);
|
||||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
void rktio_poll_set_add_handle(HANDLE h, rktio_poll_set_t *fds, int repost);
|
||||
void rktio_poll_set_add_eventmask(rktio_poll_set_t *fds, int mask);
|
||||
void rktio_poll_set_add_handle(rktio_t *rktio, HANDLE h, rktio_poll_set_t *fds, int repost);
|
||||
void rktio_poll_set_add_eventmask(rktio_t *rktio, rktio_poll_set_t *fds, int mask);
|
||||
#endif
|
||||
|
||||
/*************************************************/
|
||||
|
@ -204,7 +251,7 @@ int rktio_delete_file(rktio_t *rktio, char *fn, int enable_write_on_fail);
|
|||
int rktio_rename_file(rktio_t *rktio, char *dest, char *src, int exists_ok);
|
||||
|
||||
char *rktio_get_current_directory(rktio_t *rktio);
|
||||
int rktio_set_current_directory(rktio_t *rktio, char *expanded);
|
||||
int rktio_set_current_directory(rktio_t *rktio, const char *path);
|
||||
int rktio_make_directory(rktio_t *rktio, char *filename);
|
||||
int rktio_delete_directory(rktio_t *rktio, char *filename, char *current_directory, int enable_write_on_fail);
|
||||
|
||||
|
|
12
racket/src/rktio/rktio_envvars.c
Normal file
12
racket/src/rktio/rktio_envvars.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "rktio.h"
|
||||
#include "rktio_private.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars)
|
||||
{
|
||||
void *p;
|
||||
p = malloc(sizeof(char *));
|
||||
*(char **)p = NULL;
|
||||
return p;
|
||||
}
|
|
@ -630,12 +630,12 @@ char *rktio_get_current_directory(rktio_t *rktio)
|
|||
#endif
|
||||
}
|
||||
|
||||
int rktio_set_current_directory(rktio_t *rktio, char *expanded)
|
||||
int rktio_set_current_directory(rktio_t *rktio, const char *path)
|
||||
{
|
||||
int err;
|
||||
|
||||
while (1) {
|
||||
err = MSC_W_IZE(chdir)(MSC_WIDE_PATH_temp(expanded));
|
||||
err = MSC_W_IZE(chdir)(MSC_WIDE_PATH_temp(path));
|
||||
if (!err || (errno != EINTR))
|
||||
break;
|
||||
}
|
||||
|
@ -914,7 +914,7 @@ int rktio_delete_directory(rktio_t *rktio, char *filename, char *current_directo
|
|||
# ifdef RKTIO_SYSTEM_WINDOWS
|
||||
else if ((errno == EACCES) && !tried_cwd) {
|
||||
/* Maybe we're using the target directory. Try a real setcwd. */
|
||||
(void)rktio_set_current_directory(current_directory);
|
||||
(void)rktio_set_current_directory(rktio, current_directory);
|
||||
tried_cwd = 1;
|
||||
} else if ((errno == EACCES) && !tried_perm && enable_write_on_fail) {
|
||||
/* Maybe the directory doesn't have write permission. */
|
||||
|
|
|
@ -15,12 +15,18 @@ rktio_t *rktio_init(void)
|
|||
rktio_destroy(rktio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (!rktio_process_init(rktio)) {
|
||||
rktio_destroy(rktio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rktio;
|
||||
}
|
||||
|
||||
void rktio_destroy(rktio_t *rktio)
|
||||
{
|
||||
rktio_process_deinit(rktio);
|
||||
rktio_free_ghbn(rktio);
|
||||
rktio_free_global_poll_set(rktio);
|
||||
free(rktio);
|
||||
|
|
|
@ -72,6 +72,16 @@ struct rktio_t {
|
|||
HANDLE ghbn_start;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(RKTIO_SYSTEM_UNIX) && !defined(RKTIO_USE_PTHREADS)
|
||||
struct System_Child *system_children;
|
||||
int need_to_check_children;
|
||||
int in_sigchld_chain;
|
||||
struct rktio_t *next; /* chaining for SIGCHLD handling */
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
uintptr_t process_children_msecs;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*========================================================================*/
|
||||
|
@ -165,6 +175,13 @@ intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr
|
|||
void rktio_free_ghbn(rktio_t *rktio);
|
||||
|
||||
const char *rktio_gai_strerror(int errnum);
|
||||
|
||||
/*========================================================================*/
|
||||
/* Processes */
|
||||
/*========================================================================*/
|
||||
|
||||
int rktio_process_init(rktio_t *rktio);
|
||||
void rktio_process_deinit(rktio_t *rktio);
|
||||
|
||||
/*========================================================================*/
|
||||
/* Misc */
|
||||
|
@ -196,3 +213,5 @@ void rktio_get_windows_error(rktio_t *rktio);
|
|||
#else
|
||||
# define RKTIO_NONBLOCKING FNDELAY
|
||||
#endif
|
||||
|
||||
void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars);
|
||||
|
|
1597
racket/src/rktio/rktio_process.c
Normal file
1597
racket/src/rktio/rktio_process.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user