rktio: compiles for Windows using MinGW

This commit is contained in:
Matthew Flatt 2017-06-13 06:53:10 -06:00
parent 9bfaaf3ab3
commit a929c58712
14 changed files with 269 additions and 173 deletions

View File

@ -27,15 +27,15 @@ OBJS = rktio_fs.@LTO@ \
rktio_wide.@LTO@ \
rktio_main.@LTO@
librktio.@LIBSFX@: $(OBJS)
$(NICEAR) $(AR) $(ARFLAGS) librktio.@LIBSFX@ $(OBJS)
$(RANLIB) librktio.@LIBSFX@
librktio.@LTA@: $(OBJS)
$(NICEAR) $(AR) $(ARFLAGS) librktio.@LTA@ $(OBJS)
$(RANLIB) librktio.@LTA@
demo: rktio_demo
./rktio_demo
./rktio_demo $(ARGS)
rktio_demo: librktio.@LIBSFX@ demo.@LTO@ demo_fifo
$(RKTLINKER) -o rktio_demo $(CFLAGS) $(LDFLAGS) demo.@LTO@ librktio.@LIBSFX@ $(LIBS)
rktio_demo: librktio.@LTA@ demo.@LTO@ demo_fifo
$(RKTLINKER) -o rktio_demo $(CFLAGS) $(LDFLAGS) demo.@LTO@ librktio.@LTA@ $(LIBS)
demo_fifo:
mkfifo demo_fifo
@ -80,4 +80,4 @@ demo.@LTO@: $(srcdir)/demo.c $(RKTIO_HEADERS)
$(CC) $(CFLAGS) -I$(srcdir) -I. -o demo.@LTO@ -c $(srcdir)/demo.c
clean:
rm -f $(OBJS) librktio.@LIBSFX@ rktio_demo demo_fifo
rm -f $(OBJS) librktio.@LTA@ rktio_demo demo_fifo

View File

@ -456,8 +456,14 @@ int main(int argc, char **argv)
else if (!strcmp(argv[i], "--sleep-blocks-sigchld")) {
/* Seems useful for Valgrind on MacOS */
dont_rely_on_sigchild = 1;
} else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
printf("Recognized flags:\n");
printf(" -v : verbose\n");
printf(" --sleep-blocks-sigchld : Valgrind workaround\n");
printf(" -h, --help : this help\n");
return 0;
} else {
printf(" unrecognized flag %s\n", argv[i]);
printf(" unrecognized flag: %s\n", argv[i]);
return 1;
}
}
@ -877,7 +883,7 @@ int main(int argc, char **argv)
free(result);
}
rktio_ennvars_free(rktio, envvars);
rktio_envvars_free(rktio, envvars);
rktio_forget(rktio, err_fd);
}
@ -902,13 +908,18 @@ int main(int argc, char **argv)
rktio_poll_add_fs_change(rktio, fc, ps);
rktio_sleep(rktio, 0.1, ps, NULL);
rktio_poll_set_close(rktio, ps);
/* FIXME: check that at least 0.1 seconds have passed */
ps = rktio_make_poll_set(rktio);
check_valid(ps);
rktio_poll_add_fs_change(rktio, fc, ps);
fd2 = rktio_open(rktio, "test1", RKTIO_OPEN_WRITE | RKTIO_OPEN_CAN_EXIST);
check_valid(fd2);
amt = rktio_write(rktio, fd2, "hola", 4);
check_valid(amt == 4);
rktio_sleep(rktio, 0, ps, NULL);
check_valid(rktio_poll_fs_change_ready(rktio, fc) == RKTIO_POLL_READY);
check_valid(rktio_poll_fs_change_ready(rktio, fc) == RKTIO_POLL_READY);

View File

@ -43,6 +43,8 @@ int rktio_fd_is_regular_file(rktio_t *rktio, rktio_fd_t *rfd);
int rktio_fd_is_socket(rktio_t *rktio, rktio_fd_t *rfd);
int rktio_fd_is_udp(rktio_t *rktio, rktio_fd_t *rfd);
int rktio_fd_modes(rktio_t *rktio, rktio_fd_t *rfd);
rktio_fd_t *rktio_open(rktio_t *rktio, char *src, int modes);
int rktio_close(rktio_t *rktio, rktio_fd_t *fd);
@ -151,7 +153,7 @@ int rktio_setenv(rktio_t *rktio, const char *name, const char *val);
rktio_envvars_t *rktio_envvars(rktio_t *rktio);
rktio_envvars_t *rktio_empty_envvars(rktio_t *rktio);
rktio_envvars_t *rktio_envvars_copy(rktio_t *rktio, rktio_envvars_t *envvars);
void rktio_ennvars_free(rktio_t *rktio, rktio_envvars_t *envvars);
void rktio_envvars_free(rktio_t *rktio, rktio_envvars_t *envvars);
char *rktio_envvars_get(rktio_t *rktio, rktio_envvars_t *envvars, char *name);
void rktio_envvars_set(rktio_t *rktio, rktio_envvars_t *envvars, char *name, char *value);
@ -219,8 +221,8 @@ int rktio_poll_fs_change_ready(rktio_t *rktio, rktio_fs_change_t *fc);
/*************************************************/
/* File-descriptor sets for polling */
/* A poll set is intended for a single use or few uses, as opposed to
"long-term" poll sets. */
/* A poll set works for a single use via rktio_sleep(), as opposed to
"long-term" poll sets that can be used multiple times. */
typedef struct rktio_poll_set_t rktio_poll_set_t;

View File

@ -25,3 +25,6 @@ typedef unsigned long uintptr_t;
/* Whether getaddrinfo() is available: */
#undef HAVE_GETADDRINFO
/* In case you want to avoid dynamic sizing of `fd_set` arrays: */
#undef RKTIO_STATIC_FDSET_SIZE

View File

@ -80,14 +80,14 @@ int rktio_setenv(rktio_t *rktio, const char *name, const char *val)
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
int rc;
char *val_w;
wchar_t *val_w;
if (val)
val_w = WIDE_PATH_copy(val);
else
val_w = NULL;
rc = SetEnvironmentVariableW(WIDE_PATH_temp(var), val_w);
rc = SetEnvironmentVariableW(WIDE_PATH_temp(name), val_w);
if (val_w)
free(val_w);
@ -123,7 +123,7 @@ rktio_envvars_t *rktio_envvars(rktio_t *rktio)
i++;
}
ennvars = malloc(sizeof(rktio_envvars_t));
envvars = malloc(sizeof(rktio_envvars_t));
envvars->size = count;
envvars->count = count;
envvars->names = malloc(count * sizeof(char *));
@ -209,7 +209,7 @@ rktio_envvars_t *rktio_envvars_copy(rktio_t *rktio, rktio_envvars_t *envvars)
return new_envvars;
}
void rktio_ennvars_free(rktio_t *rktio, rktio_envvars_t *envvars)
void rktio_envvars_free(rktio_t *rktio, rktio_envvars_t *envvars)
{
int i;
@ -353,12 +353,12 @@ for (i = 0; i < envvars->count; i++) {
for (i = 0; i < envvars->count; i++) {
s = WIDE_PATH_temp(envvars->names[i]);
slen = wc_strlen(s);
memcpy(r XFORM_OK_PLUS len, s, slen * sizeof(wchar_t));
memcpy(r + len, s, slen * sizeof(wchar_t));
len += slen;
r[len++] = '=';
s = WIDE_PATH(envvars->vals[i]);
s = WIDE_PATH_temp(envvars->vals[i]);
slen = wc_strlen(s);
memcpy(r XFORM_OK_PLUS len, s, slen * sizeof(wchar_t));
memcpy(r + len, s, slen * sizeof(wchar_t));
len += slen;
r[len++] = 0;
}

View File

@ -37,7 +37,8 @@ struct rktio_fd_t {
};
struct Win_FD_Input_Thread *th; /* input mode */
struct Win_FD_Output_Thread *oth; /* output mode */
char *buffer;
int unblocked; /* whether non-blocking mode is installed */
char *buffer; /* shared with reading thread */
#endif
};
@ -86,6 +87,31 @@ typedef struct Win_FD_Output_Thread {
# define RKTIO_FD_BUFFSIZE 4096
static long WINAPI WindowsFDReader(Win_FD_Input_Thread *th);
static void WindowsFDICleanup(Win_FD_Input_Thread *th);
static long WINAPI WindowsFDWriter(Win_FD_Output_Thread *oth);
static void WindowsFDOCleanup(Win_FD_Output_Thread *oth);
typedef BOOL (WINAPI* CSI_proc)(HANDLE);
static CSI_proc get_csi(void)
{
static int tried_csi = 0;
static CSI_proc csi;
if (!tried_csi) {
HMODULE hm;
hm = LoadLibrary("kernel32.dll");
if (hm)
csi = (CSI_proc)GetProcAddress(hm, "CancelSynchronousIo");
else
csi = NULL;
tried_csi = 1;
}
return csi;
}
#endif
/*========================================================================*/
@ -135,7 +161,6 @@ static void init_read_fd(rktio_t *rktio, rktio_fd_t *rfd)
th->ready_sema = sm;
sm = CreateSemaphore(NULL, 1, 1, NULL);
th->you_clean_up_sema = sm;
th->refcount = refcount;
h = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)WindowsFDReader, th, 0, &id);
@ -166,7 +191,7 @@ rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes)
#ifdef RKTIO_SYSTEM_WINDOWS
if (modes & RKTIO_OPEN_SOCKET)
rfd->s = system_fd;
rfd->sock = system_fd;
else
rfd->fd = (HANDLE)system_fd;
if (!(modes & (RKTIO_OPEN_REGFILE | RKTIO_OPEN_NOT_REGFILE | RKTIO_OPEN_SOCKET))) {
@ -320,7 +345,7 @@ int rktio_close(rktio_t *rktio, rktio_fd_t *rfd)
WindowsFDOCleanup(rfd->oth);
} /* otherwise, thread is responsible for clean-up */
}
if (!rfp->th && !rfp->oth) {
if (!rfd->th && !rfd->oth) {
CloseHandle(rfd->fd);
}
#endif
@ -434,7 +459,7 @@ int rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd)
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
if (rfd->modes & RKTIO_OPEN_SOCKET)
return rktio_socket_poll_read_ready(rktio, rfd->sock);
return rktio_socket_poll_read_ready(rktio, rfd);
if (!rfd->th) {
/* No thread -- so wait works. This case isn't actually used
@ -511,7 +536,7 @@ int poll_write_ready_or_flushed(rktio_t *rktio, rktio_fd_t *rfd, int check_flush
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
if (rfd->modes & RKTIO_OPEN_SOCKET)
return rktio_socket_poll_write_ready(rktio, rfd->sock);
return rktio_socket_poll_write_ready(rktio, rfd);
if (rfd->oth) {
/* Pipe output that can block... */
@ -606,10 +631,10 @@ void rktio_poll_add(rktio_t *rktio, rktio_fd_t *rfd, rktio_poll_set_t *fds, int
}
if (modes & RKTIO_POLL_WRITE) {
if (rfp->oth && !fd_write_ready(port))
rktio_fdset_add_handle(rfp->oth->ready_sema, fds, 1);
if (rfd->oth && !rktio_poll_write_ready(rktio, rfd))
rktio_poll_set_add_handle(rfd->oth->ready_sema, fds, 1);
else
rktio_fdset_nosleep(fds);
rktio_poll_set_nosleep(fds);
}
}
#endif
@ -707,7 +732,7 @@ intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
} else {
intptr_t bc = rfd->th->avail;
rfd->th->avail = 0;
FIXME read the data;
memcpy(buffer, rfd->buffer, bc);
return bc;
}
}
@ -779,7 +804,6 @@ static void WindowsFDICleanup(Win_FD_Input_Thread *th)
CloseHandle(th->ready_sema);
CloseHandle(th->you_clean_up_sema);
rc = adj_refcount(th->refcount, -1);
if (!rc) CloseHandle(th->fd);
free(th->buffer);
@ -849,13 +873,14 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len
is ERROR_NOT_ENOUGH_MEMORY (as opposed to a partial write). */
int ok;
intptr_t towrite = len;
int err;
while (1) {
ok = WriteFile((HANDLE)rfd->fd, buffer, towrite, &winwrote, NULL);
if (!ok)
errsaved = GetLastError();
err = GetLastError();
if (!ok && (errsaved == ERROR_NOT_ENOUGH_MEMORY)) {
if (!ok && (err == ERROR_NOT_ENOUGH_MEMORY)) {
towrite = towrite >> 1;
if (!towrite)
break;
@ -1000,7 +1025,6 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len
oth->ready_sema = sm;
sm = CreateSemaphore(NULL, 1, 1, NULL);
oth->you_clean_up_sema = sm;
oth->refcount = rfd->refcount;
h = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)WindowsFDWriter, oth, 0, &id);
@ -1100,55 +1124,84 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len
#endif
}
/*========================================================================*/
/* refcounts for Windows fd threads */
/*========================================================================*/
#ifdef RKTIO_SYSTEM_WINDOWS
#if defined(WINDOWS_FILE_HANDLES) || defined(MZ_USE_PLACES)
# define MZ_LOCK_REFCOUNTS
static mzrt_mutex *refcount_mutex;
#endif
static int *malloc_refcount(int val, int free_on_zero)
static long WINAPI WindowsFDWriter(Win_FD_Output_Thread *oth)
{
int *rc;
DWORD towrite, wrote, start;
int ok, more_work = 0, err_no;
#ifdef MZ_LOCK_REFCOUNTS
if (!refcount_mutex)
mzrt_mutex_create(&refcount_mutex);
#endif
if (oth->nonblocking) {
/* Non-blocking mode (Win NT pipes). Just flush. */
while (!oth->done) {
WaitForSingleObject(oth->work_sema, INFINITE);
rc = (int *)malloc(2 * sizeof(int));
*rc = val;
rc[1] = free_on_zero;
FlushFileBuffers(oth->fd);
return rc;
WaitForSingleObject(oth->lock_sema, INFINITE);
oth->flushed = 1;
ReleaseSemaphore(oth->ready_sema, 1, NULL);
ReleaseSemaphore(oth->lock_sema, 1, NULL);
}
} else {
/* Blocking mode. We do the writing work. This case is for
Win 95/98/Me anonymous pipes and character devices (such
as LPT1). */
while (!oth->err_no) {
if (!more_work)
WaitForSingleObject(oth->work_sema, INFINITE);
if (oth->done)
break;
WaitForSingleObject(oth->lock_sema, INFINITE);
towrite = oth->buflen;
if (towrite > (RKTIO_FD_BUFFSIZE - oth->bufstart))
towrite = RKTIO_FD_BUFFSIZE - oth->bufstart;
start = oth->bufstart;
ReleaseSemaphore(oth->lock_sema, 1, NULL);
ok = WriteFile(oth->fd, oth->buffer + start, towrite, &wrote, NULL);
if (!ok)
err_no = GetLastError();
else
err_no = 0;
WaitForSingleObject(oth->lock_sema, INFINITE);
if (!ok)
oth->err_no = err_no;
else {
oth->bufstart += wrote;
oth->buflen -= wrote;
if (oth->bufstart == RKTIO_FD_BUFFSIZE)
oth->bufstart = 0;
more_work = oth->buflen > 0;
}
if ((oth->buflen < RKTIO_FD_BUFFSIZE) || oth->err_no)
ReleaseSemaphore(oth->ready_sema, 1, NULL);
ReleaseSemaphore(oth->lock_sema, 1, NULL);
}
}
if (WaitForSingleObject(oth->you_clean_up_sema, 0) != WAIT_OBJECT_0) {
WindowsFDOCleanup(oth);
} /* otherwise, main thread is responsible for clean-up */
return 0;
}
static int adj_refcount(int *refcount, int amt)
XFORM_SKIP_PROC
static void WindowsFDOCleanup(Win_FD_Output_Thread *oth)
{
int rc;
if (!refcount)
return 0;
CloseHandle(oth->lock_sema);
CloseHandle(oth->work_sema);
CloseHandle(oth->you_clean_up_sema);
if (!rc) CloseHandle(oth->fd);
#ifdef MZ_LOCK_REFCOUNTS
mzrt_mutex_lock(refcount_mutex);
#endif
if (amt > 0) {
/* don't increment up from 0 */
if (*refcount)
*refcount += amt;
} else
*refcount += amt;
rc = *refcount;
#ifdef MZ_LOCK_REFCOUNTS
mzrt_mutex_unlock(refcount_mutex);
#endif
if (!rc && refcount[1])
free(refcount);
return rc;
if (oth->buffer)
free(oth->buffer);
free(oth);
}
#endif

View File

@ -61,7 +61,7 @@ static rktio_fd_t *open_read(rktio_t *rktio, char *filename)
#ifdef RKTIO_SYSTEM_WINDOWS
HANDLE fd;
fd = CreateFileW(WIDE_PATH(filename),
fd = CreateFileW(WIDE_PATH_temp(filename),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
@ -163,7 +163,7 @@ static rktio_fd_t *open_write(rktio_t *rktio, char *filename, int modes)
rktio_fd_t *rfd;
if (modes & RKTIO_OPEN_MUST_EXIST) {
if (modes & RKTIO_OPEN_TRUNNCATE)
if (modes & RKTIO_OPEN_TRUNCATE)
hmode = TRUNCATE_EXISTING;
else
hmode = OPEN_EXISTING;
@ -183,7 +183,7 @@ static rktio_fd_t *open_write(rktio_t *rktio, char *filename, int modes)
if (fd == INVALID_HANDLE_VALUE) {
int errv;
errv = GetLastError();
if ((errv == ERROR_ACCESS_DENIED) && (existsok < -1)) {
if ((errv == ERROR_ACCESS_DENIED) && (modes & RKTIO_OPEN_REPLACE)) {
/* Delete and try again... */
if (DeleteFileW(WIDE_PATH_temp(filename))) {
fd = CreateFileW(WIDE_PATH_temp(filename),
@ -220,7 +220,7 @@ static rktio_fd_t *open_write(rktio_t *rktio, char *filename, int modes)
}
}
rfd = rktio_system_fd(rktio, fd, modes);
rfd = rktio_system_fd(rktio, (intptr_t)fd, modes);
if ((modes & RKTIO_OPEN_APPEND) && rktio_fd_is_regular_file(rktio, rfd)) {
SetFilePointer(fd, 0, NULL, FILE_END);

View File

@ -121,7 +121,7 @@ rktio_fs_change_t *rktio_fs_change(rktio_t *rktio, char *path)
{
HANDLE h;
h = FindFirstChangeNotificationW(WIDE_PATH_tmp(try_path), FALSE,
h = FindFirstChangeNotificationW(WIDE_PATH_temp(path), FALSE,
(FILE_NOTIFY_CHANGE_FILE_NAME
| FILE_NOTIFY_CHANGE_DIR_NAME
| FILE_NOTIFY_CHANGE_SIZE

View File

@ -21,6 +21,8 @@ rktio_t *rktio_init(void)
return NULL;
}
rktio_useless_wide();
return rktio;
}

View File

@ -15,7 +15,7 @@
# include <fcntl.h>
# include <errno.h>
# define TCP_SOCKSENDBUF_SIZE 32768
# define NOT_WINSOCK(x) x
# define NOT_WINSOCK(x) (x)
# define SOCK_ERRNO() errno
# define WAS_EAGAIN(e) ((e == EWOULDBLOCK) || (e == EAGAIN) || (e == EINPROGRESS) || (e == EALREADY))
# define WAS_ECONNREFUSED(e) (e == ECONNREFUSED)
@ -133,7 +133,7 @@ struct rktio_udp_t {
};
#if RKTIO_SYSTEM_WINDOWS
#ifdef RKTIO_SYSTEM_WINDOWS
# define DECL_SOCK_FDSET(n) fd_set n[1]
# define INIT_DECL_SOCK_FDSET(r, w, e) /* empty */
# define INIT_DECL_SOCK_RD_FDSET(r) /* empty */
@ -344,7 +344,7 @@ static void ghbn_lock(rktio_t *rktio)
static void ghbn_unlock(rktio_t *rktio)
{
ReleaseSemaphore(data->ghbn_lock, 1, NULL);
ReleaseSemaphore(rktio->ghbn_lock, 1, NULL);
}
static void ghbn_wait(rktio_t *rktio)
@ -356,12 +356,12 @@ static void ghbn_wait(rktio_t *rktio)
static void ghbn_signal(rktio_t *rktio)
{
ReleaseSemaphore(data->ghbn_ready, 1, NULL);
ReleaseSemaphore(rktio->ghbn_start, 1, NULL);
}
static void ghbn_wait_exit(rktio_t *rktio)
{
WaitForSingleObject(rktio->th, INFINITE);
WaitForSingleObject(rktio->ghbn_th, INFINITE);
}
# else
@ -416,7 +416,7 @@ static intptr_t getaddrinfo_in_thread(void *_data)
ghbn_lock(rktio);
# ifdef RKTIO_SYSTEM_WINDOWS
ReleaseSemaphore(data->ready_sema, 1, NULL);
ReleaseSemaphore(lookup->done_sema, 1, NULL);
# else
{
long v = 1;
@ -429,7 +429,7 @@ static intptr_t getaddrinfo_in_thread(void *_data)
if (lookup->mode == GHBN_ABANDONED) {
# ifdef RKTIO_SYSTEM_WINDOWS
CloseHandle(data->ready_sema);
CloseHandle(lookup->done_sema);
# else
rktio_reliably_close(lookup->done_fd[0]);
# endif
@ -464,10 +464,10 @@ static int ghbn_init(rktio_t *rktio)
get_windows_error();
return 0;
}
rktio->th = (HANDLE)_beginthreadex(NULL, 5000,
win_getaddrinfo_in_thread,
rktio, 0, &id);
if (rktio->th == INVALID_HANDLE) {
rktio->ghbn_th = (HANDLE)_beginthreadex(NULL, 5000,
win_getaddrinfo_in_thread,
rktio, 0, NULL);
if (rktio->ghbn_th == INVALID_HANDLE_VALUE) {
get_posix_error();
return 0;
}
@ -881,8 +881,9 @@ int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd)
return rktio_close(rktio, rfd);
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
UNREGISTER_SOCKET(rfd->sock);
closesocket(rfd->sock);
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
UNREGISTER_SOCKET(s);
closesocket(s);
free(rfd);
return 1;
@ -895,8 +896,9 @@ void rktio_socket_forget(rktio_t *rktio, rktio_fd_t *rfd)
rktio_forget(rktio, rfd);
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
UNREGISTER_SOCKET(rfd->sock);
closesocket(rfd->sock);
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
UNREGISTER_SOCKET(s);
closesocket(s);
#endif
}
@ -955,7 +957,7 @@ int rktio_socket_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd)
RKTIO_SOCK_FD_ZERO(exnfds);
RKTIO_SOCK_FD_SET(s, exnfds);
sr = select(s + 1, readfdsfds, NULL, exnfds, &time);
sr = select(s + 1, readfds, NULL, exnfds, &time);
if (sr == -1) {
get_socket_error();
@ -987,10 +989,11 @@ rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd)
return rktio_dup(rktio, rfd);
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
intptr_t nsocket;
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
rktio_socket_t nsocket;
intptr_t rc;
WSAPROTOCOL_INFO protocolInfo;
rc = WSADuplicateSocket(rfd->sock, GetCurrentProcessId(), &protocolInfo);
rc = WSADuplicateSocket(s, GetCurrentProcessId(), &protocolInfo);
if (rc) {
get_socket_error();
return NULL;
@ -1001,7 +1004,7 @@ rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd)
return NULL;
}
REGISTER_SOCKET(nsocket);
return rktio_system_fd(nsocket, rfd->modes);
return rktio_system_fd(rktio, nsocket, rktio_fd_modes(rktio, rfd));
#endif
}
@ -1012,7 +1015,7 @@ intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr
do {
rn = recv(s, buffer, len, 0);
} while ((rn == -1) && (NOT_WINSOCK(errno) == EINTR));
} while ((rn == -1) && NOT_WINSOCK(errno == EINTR));
if (rn > 0)
return rn;
@ -1054,7 +1057,7 @@ static intptr_t do_socket_write(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, i
do {
sent = sendto(s, buffer, len, 0,
RKTIO_AS_ADDRINFO(addr)->ai_addr, RKTIO_AS_ADDRINFO(addr)->ai_addrlen);
} while ((sent == -1) && (NOT_WINSOCK(errno) == EINTR));
} while ((sent == -1) && NOT_WINSOCK(errno == EINTR));
if (sent >= 0)
break;
errid = SOCK_ERRNO();
@ -1064,7 +1067,7 @@ static intptr_t do_socket_write(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, i
} else {
do {
sent = send(s, buffer, len, 0);
} while ((sent == -1) && (NOT_WINSOCK(errno) == EINTR));
} while ((sent == -1) && NOT_WINSOCK(errno == EINTR));
if (sent == -1)
errid = SOCK_ERRNO();
@ -1206,7 +1209,7 @@ rktio_fd_t *rktio_connect_finish(rktio_t *rktio, rktio_connect_t *conn)
if (!rktio->windows_nt_or_later && !errid) {
/* getsockopt() seems not to work in Windows 95, so use the
result from select(), which seems to reliably detect an error condition */
if (rktio_poll_connect_ready() == RKTIO_POLL_ERROR) {
if (rktio_poll_connect_ready(rktio, conn) == RKTIO_POLL_ERROR) {
errid = WSAECONNREFUSED; /* guess! */
}
}
@ -1517,7 +1520,7 @@ static int do_poll_accept_ready(rktio_t *rktio, rktio_listener_t *listener, int
do {
sr = select(mx + 1, RKTIO_SOCK_FDS(readfds), NULL, RKTIO_SOCK_FDS(exnfds), &time);
} while ((sr == -1) && (NOT_WINSOCK(errno) == EINTR));
} while ((sr == -1) && NOT_WINSOCK(errno == EINTR));
if (sr > 0) {
if (report_which) {
@ -1578,7 +1581,7 @@ rktio_fd_t *rktio_accept(rktio_t *rktio, rktio_listener_t *listener)
do {
s = accept(ls, (struct sockaddr *)tcp_accept_addr, &l);
} while ((s == -1) && (NOT_WINSOCK(errno) == EINTR));
} while ((s == -1) && NOT_WINSOCK(errno == EINTR));
if (s != INVALID_SOCKET) {
# ifdef RKTIO_SYSTEM_UNIX
@ -1805,7 +1808,7 @@ rktio_length_and_addrinfo_t *rktio_udp_recvfrom(rktio_t *rktio, rktio_fd_t *rfd,
/* => data truncated on Windows, which counts as success on Unix */
rn = len;
break;
} else if (NOT_WINSOCK(errno) == EINTR) {
} else if (NOT_WINSOCK(errno == EINTR)) {
/* try again */
} else if (WAS_EAGAIN(errno)) {
/* no data available */

View File

@ -323,9 +323,7 @@ static rktio_poll_set_t *alloc_fdset_arrays()
"max" fd counter, and 1 extra intger used to record "no
sleeping" */
p = malloc((3 * (dynamic_fd_size + sizeof(intptr_t))) + sizeof(int));
*(int *)((char *)p + (3 * (dynamic_fd_size + sizeof(intptr_t)))) = 0;
p = malloc(3 * (dynamic_fd_size + sizeof(intptr_t) + sizeof(int)));
return p;
}
@ -337,7 +335,7 @@ static void free_fdset_arrays(rktio_poll_set_t *fds)
rktio_poll_set_t *rktio_get_fdset(rktio_poll_set_t *fdarray, int pos)
{
return (rktio_poll_set_t *)(((char *)fdarray) + (pos * (dynamic_fd_size + sizeof(intptr_t))));
return (rktio_poll_set_t *)(((char *)fdarray) + (pos * (dynamic_fd_size + sizeof(intptr_t) + sizeof(int))));
}
void rktio_fdzero(rktio_poll_set_t *fd)
@ -347,12 +345,12 @@ void rktio_fdzero(rktio_poll_set_t *fd)
void rktio_poll_set_add_nosleep(rktio_t *rktio, rktio_poll_set_t *fds)
{
*(int *)((char *)fds + (3 * (dynamic_fd_size + sizeof(intptr_t)))) = 1;
*(int *)((char *)fds + dynamic_fd_size + sizeof(intptr_t)) = 1;
}
static int fdset_has_nosleep(rktio_poll_set_t *fds)
{
return *(int *)((char *)fds + (3 * (dynamic_fd_size + sizeof(intptr_t))));
return *(int *)((char *)fds + dynamic_fd_size + sizeof(intptr_t));
}
/* Continues below: */
@ -364,13 +362,13 @@ static int fdset_has_nosleep(rktio_poll_set_t *fds)
/* Windows variant */
/*========================================================================*/
typedef struct {
struct rktio_poll_set_t {
SOCKET *sockets;
intptr_t added, alloc, last_alloc;
intptr_t num_handles, alloc_handles, last_alloc_handles;
OS_SEMAPHORE_TYPE *handles;
HANDLE *handles;
int *repost_sema;
@ -382,7 +380,9 @@ typedef struct {
HANDLE *combined_wait_array;
intptr_t combined_len;
} rktio_poll_set_t;
};
static void reset_wait_array(rktio_poll_set_t *efd);
static void init_fdset_array(rktio_poll_set_t *fdarray, int count)
{
@ -421,18 +421,26 @@ static void init_fdset_array(rktio_poll_set_t *fdarray, int count)
static rktio_poll_set_t *alloc_fdset_arrays()
{
rktio_poll_set_t *fdarray;
if (count) {
fdarray = calloc(3, sizeof(rktio_poll_set_t));
init_fdset_array(fdarray, 3);
} else
fdarray = NULL;
fdarray = calloc(3, sizeof(rktio_poll_set_t));
init_fdset_array(fdarray, 3);
return fdarray;
}
static void free_fdset_arrays(rktio_poll_set_t *fds)
{
FIXME;
int i;
for (i = 0; i < 3; i++) {
if (fds[i].handles)
free(fds[i].handles);
if (fds[i].repost_sema)
free(fds[i].repost_sema);
if (fds[i].wait_array)
free(fds[i].wait_array);
}
free(fds);
}
static void reset_wait_array(rktio_poll_set_t *efd)
@ -473,7 +481,7 @@ void rktio_fdset(rktio_poll_set_t *fd, int n)
if (fd->added >= fd->last_alloc) {
int na;
na = next_size(fd->last_alloc);
efd->last_alloc = na;
fd->last_alloc = na;
}
if (fd->added >= fd->alloc) {
SOCKET *naya;
@ -502,9 +510,9 @@ int rktio_fdisset(rktio_poll_set_t *fd, int n)
void rktio_merge_fd_sets(rktio_poll_set_t *fds, rktio_poll_set_t *src_fds)
{
int i;
for (i = src_fd->added; i--; ) {
if (stv_fd->sockets[i] != INVALID_SOCKET)
rktio_fdset(fds, src_fd->sockets[i]);
for (i = src_fds->added; i--; ) {
if (src_fds->sockets[i] != INVALID_SOCKET)
rktio_fdset(fds, src_fds->sockets[i]);
}
}
@ -520,7 +528,7 @@ int rktio_get_fd_limit(rktio_poll_set_t *fds)
void rktio_poll_set_add_handle(HANDLE h, rktio_poll_set_t *fds, int repost)
{
rktio_poll_set_t *efd = fds;
OS_SEMAPHORE_TYPE *hs;
HANDLE *hs;
int i, new_i, *rps;
if (efd->num_handles == efd->last_alloc_handles) {
@ -733,10 +741,7 @@ void rktio_collapse_win_fd(rktio_poll_set_t *fds)
static rktio_poll_set_t *alloc_fdset_arrays()
{
void *p;
p = malloc((3 * sizeof(fd_set)) + sizeof(int));
*(int *)((char *)p + (3 * sizeof(fd_set))) = 0;
return p;
return malloc(3 * sizeof(rktio_poll_set_t));
}
static void free_fdset_arrays(rktio_poll_set_t *fds)
@ -752,16 +757,17 @@ rktio_poll_set_t *rktio_get_fdset(rktio_poll_set_t *fdarray, int pos)
void rktio_fdzero(rktio_poll_set_t *fd)
{
FD_ZERO(&(fd)->data);
fd->nosleep = 0;
}
void rktio_poll_set_add_nosleep(rktio_t *rktio, rktio_poll_set_t *fds)
{
*(int *)((char *)fds + (3 * sizeof(fd_set))) = 1;
fds->nosleep = 1;
}
static int fdset_has_nosleep(rktio_poll_set_t *fds)
{
return *(int *)((char *)fds + (3 * sizeof(fd_set)));
return fds->nosleep;
}
#define USE_PLAIN_FDS_SET_OPS
@ -813,6 +819,8 @@ void rktio_merge_fd_sets(rktio_poll_set_t *fds, rktio_poll_set_t *src_fds)
*p |= *sp;
}
}
if (fdset_has_nosleep(src_fds))
rktio_poll_set_add_nosleep(NULL, fds);
}
void rktio_clean_fd_set(rktio_poll_set_t *fds)
@ -1000,9 +1008,10 @@ void rktio_wait_until_signal_received(rktio_t *rktio)
/****************** Windows cleanup *****************/
#if RKTIO_SYSTEM_WINDOWS
#ifdef RKTIO_SYSTEM_WINDOWS
static void clean_up_wait(intptr_t result, OS_SEMAPHORE_TYPE *array,
static void clean_up_wait(rktio_t *rktio,
intptr_t result, HANDLE *array,
int *rps, int count)
{
if ((result >= (intptr_t)WAIT_OBJECT_0) && (result < (intptr_t)WAIT_OBJECT_0 + count)) {
@ -1012,7 +1021,7 @@ static void clean_up_wait(intptr_t result, OS_SEMAPHORE_TYPE *array,
}
/* Clear out break semaphore */
WaitForSingleObject((HANDLE)scheme_break_semaphore, 0);
WaitForSingleObject(rktio->break_semaphore, 0);
}
static int made_progress;
@ -1214,8 +1223,7 @@ void rktio_sleep(rktio_t *rktio, float nsecs, rktio_poll_set_t *fds, rktio_ltps_
spin and eat CPU cycles. The back-off is reset whenever a thread makes
progress. */
if (SCHEME_INT_VAL(((win_extended_fd_set *)fds)->wait_event_mask)
&& GetQueueStatus(SCHEME_INT_VAL(((win_extended_fd_set *)fds)->wait_event_mask))) {
if (fds->wait_event_mask && GetQueueStatus(fds->wait_event_mask)) {
if (!made_progress) {
/* Ok, we've gone around at least once. */
if (max_sleep_time < 0x20000000)
@ -1248,10 +1256,9 @@ void rktio_sleep(rktio_t *rktio, float nsecs, rktio_poll_set_t *fds, rktio_ltps_
msec = INFINITE;
}
result = MsgWaitForMultipleObjects(count, array, FALSE, msec,
SCHEME_INT_VAL(((win_extended_fd_set *)fds)->wait_event_mask));
result = MsgWaitForMultipleObjects(count, array, FALSE, msec, fds->wait_event_mask);
}
clean_up_wait(result, array, rps, rcount);
clean_up_wait(rktio, result, array, rps, rcount);
scheme_collapse_win_fd(fds); /* cleans up */
return;

View File

@ -10,16 +10,14 @@
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
# include <winsock2.h>
# include <windows.h>
#endif
#ifdef RKTIO_USE_PTHREADS
# include <pthread.h>
#endif
#if defined(__linux__) || defined(OS_X) || defined(__NetBSD__) \
|| defined(__NetBSD__) || defined(__OpenBSD__) \
|| defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
|| defined(__DragonFly__) || defined(__QNX__)
#if defined(RKTIO_SYSTEM_UNIX) && !defined(RKTIO_STATIC_FDSET_SIZE)
# define USE_DYNAMIC_FDSET_SIZE
#endif
@ -81,6 +79,7 @@ struct rktio_t {
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
uintptr_t process_children_msecs;
HANDLE process_job_object;
#endif
#ifdef HAVE_INOTIFY_SYSCALL
@ -134,7 +133,10 @@ int rktio_fdisset(rktio_poll_set_t *fd, int n);
#else
#include <sys/select.h>
struct rktio_poll_set_t { fd_set data; };
struct rktio_poll_set_t { fd_set data; int nosleep; };
/* Need "far" call to fdzero to deal with `nosleep`: */
void rktio_fdzero(rktio_poll_set_t *fd);
# define DECL_FDSET(n, c) rktio_poll_set_t n[c]
# define INIT_DECL_FDSET(r, w, e) /* empty */
@ -145,7 +147,7 @@ struct rktio_poll_set_t { fd_set data; };
# define RKTIO_FDS(p) (&(p)->data)
# define RKTIO_GET_FDSET(p, n) ((p)+(n))
# define RKTIO_FD_ZERO(p) FD_ZERO(RKTIO_FDS(p))
# define RKTIO_FD_ZERO(p) rktio_fdzero(p)
# define RKTIO_FD_SET(n, p) FD_SET(n, RKTIO_FDS(p))
# define RKTIO_FD_CLR(n, p) FD_CLR(n, RKTIO_FDS(p))
# define RKTIO_FD_ISSET(n, p) FD_ISSET(n, RKTIO_FDS(p))
@ -251,3 +253,7 @@ void rktio_reliably_close(intptr_t s);
void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars);
void rktio_stop_fs_change(rktio_t *rktio);
#ifdef RKTIO_SYSTEM_UNIX
void rktio_useless_wide();
#endif

View File

@ -520,8 +520,8 @@ static void do_group_signal_fds()
#ifdef RKTIO_SYSTEM_WINDOWS
# ifndef USE_CYGWIN_PIPES
# define _EXTRA_PIPE_ARGS
static int MyPipe(intptr_t *ph, int near_index)
# define _EXTRA_PIPE_ARGS , rktio
static int MyPipe(intptr_t *ph, int near_index, rktio_t *rktio)
{
HANDLE r, w;
SECURITY_ATTRIBUTES saAttr;
@ -756,10 +756,10 @@ static void collect_process_time(rktio_t *rktio, DWORD w, rktio_process_t *sp)
if ((w != STILL_ACTIVE) && !sp->got_time) {
FILETIME cr, ex, kr, us;
if (GetProcessTimes(sp->handle, &cr, &ex, &kr, &us)) {
_int64 v;
__int64 v;
uintptr_t msecs;
v = ((((_int64)kr.dwHighDateTime << 32) + kr.dwLowDateTime)
+ (((_int65)us.dwHighDateTime << 32) + us.dwLowDateTime));
v = ((((__int64)kr.dwHighDateTime << 32) + kr.dwLowDateTime)
+ (((__int64)us.dwHighDateTime << 32) + us.dwLowDateTime));
msecs = (uintptr_t)(v / 10000);
rktio->process_children_msecs += msecs;
@ -830,8 +830,7 @@ void rktio_poll_add_process(rktio_t *rktio, rktio_process_t *sp, rktio_poll_set_
}
#ifdef RKTIO_SYSTEM_WINDOWS
HANDLE sci = sp->handle;
rktio_poll_set_add_handle(rktio, handle, fds, 0);
rktio_poll_set_add_handle(rktio, sp->handle, fds, 0);
#endif
}
@ -1005,7 +1004,7 @@ void rktio_process_forget(rktio_t *rktio, rktio_process_t *sp)
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
CloseHandle(subproc->handle);
CloseHandle(sp->handle);
#endif
free(sp);
@ -1023,10 +1022,10 @@ int rktio_process_init(rktio_t *rktio)
void rktio_process_deinit(rktio_t *rktio)
{
#ifdef RKTIO_SYSTEM_WINDOWS
if (process_job_object) {
TerminateJobObject((HANDLE)process_job_object, 1);
CloseHandle((HANDLE)process_job_object);
process_job_object = NULL;
if (rktio->process_job_object) {
TerminateJobObject(rktio->process_job_object, 1);
CloseHandle(rktio->process_job_object);
rktio->process_job_object = NULL;
}
#endif
#if defined(RKTIO_SYSTEM_UNIX) && !defined(CENTRALIZED_SIGCHILD)
@ -1096,15 +1095,16 @@ static char *cmdline_protect(char *s)
return strdup(s);
}
static intptr_t do_spawnv(char *command, const char * const *argv,
static intptr_t do_spawnv(rktio_t *rktio,
const char *command, const char * const *argv,
int exact_cmdline, intptr_t sin, intptr_t sout, intptr_t serr, int *pid,
int new_process_group, int chain_termination_here_to_child,
void *env, char *wd)
void *env, const char *wd)
{
int i, l, len = 0, use_jo;
intptr_t cr_flag;
char *cmdline;
wchar_t *cmdline_w;
wchar_t *cmdline_w, *wd_w;
STARTUPINFOW startup;
PROCESS_INFORMATION info;
@ -1151,14 +1151,14 @@ static intptr_t do_spawnv(char *command, const char * const *argv,
if (use_jo) {
/* Use a job object to ensure that the new process will be terminated
if this process ends for any reason (including a crash) */
if (!process_job_object) {
GC_CAN_IGNORE JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
if (!rktio->process_job_object) {
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
process_job_object = (void*)CreateJobObject(NULL, NULL);
rktio->process_job_object = CreateJobObject(NULL, NULL);
memset(&jeli, 0, sizeof(jeli));
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject((HANDLE)process_job_object,
SetInformationJobObject(rktio->process_job_object,
JobObjectExtendedLimitInformation,
&jeli,
sizeof(jeli));
@ -1169,19 +1169,22 @@ static intptr_t do_spawnv(char *command, const char * const *argv,
cmdline_w = WIDE_PATH_copy(cmdline);
if (!exact_cmdline)
free(cmdline);
wd_w = WIDE_PATH_copy(wd);
if (CreateProcessW(WIDE_PATH_temp(command), cmdline_w,
NULL, NULL, 1 /*inherit*/,
cr_flag, env, WIDE_PATH_COPY(wd),
cr_flag, env, wd_w,
&startup, &info)) {
if (use_jo)
AssignProcessToJobObject((HANDLE)process_job_object, info.hProcess);
AssignProcessToJobObject(rktio->process_job_object, info.hProcess);
CloseHandle(info.hThread);
*pid = info.dwProcessId;
free(cmdline_w);
free(wd_w);
return (intptr_t)info.hProcess;
} else {
free(cmdline_w);
free(wd_w);
return -1;
}
}
@ -1242,10 +1245,10 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
System_Child *sc;
# endif
int fork_errno = 0;
void *env;
#else
void *sc = 0;
#endif
void *env;
rktio_process_t *subproc;
#if defined(RKTIO_SYSTEM_WINDOWS)
intptr_t spawn_status;
@ -1295,7 +1298,6 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
}
env = rktio_envvars_to_block(rktio, envvars);
#if defined(RKTIO_SYSTEM_WINDOWS)
@ -1311,7 +1313,7 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
{
char **new_argv;
if (!exact_cmdline) {
if (!windows_exact_cmdline) {
/* protect spaces, etc. in the arguments: */
new_argv = malloc(sizeof(char *) * argc);
for (i = 0; i < argc; i++) {
@ -1320,8 +1322,9 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
argv = new_argv;
}
spawn_status = do_spawnv(command, (const char * const *)new_argv,
exact_cmdline,
spawn_status = do_spawnv(rktio,
command, (const char * const *)new_argv,
windows_exact_cmdline,
to_subprocess[0],
from_subprocess[1],
err_subprocess[1],
@ -1330,7 +1333,7 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
windows_chain_termination_to_child,
env, current_directory);
if (!exact_cmdline) {
if (!windows_exact_cmdline) {
for (i = 0; i < argc; i++) {
free(argv[i]);
}
@ -1576,6 +1579,7 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
return result;
}
#ifdef RKTIO_SYSTEM_UNIX
static void close_fds_after_fork(int skip1, int skip2, int skip3)
{
int i;
@ -1596,4 +1600,4 @@ static void close_fds_after_fork(int skip1, int skip2, int skip3)
}
}
}
#endif

View File

@ -3,6 +3,11 @@
/* For converting byte strings to and from "wide" strings on Windows. */
#ifdef RKTIO_SYSTEM_UNIX
/* To avoid complaints about an empty object file */
void rktio_useless_wide() { }
#endif
#ifdef RKTIO_SYSTEM_WINDOWS
#include <inttypes.h>