rktio: repairs for Windows
Might break other systems...
This commit is contained in:
parent
773050805b
commit
1e0a55cc8f
|
@ -62,7 +62,9 @@ START_XFORM_SUSPEND;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#ifndef DOS_FILE_SYSTEM
|
||||||
|
# include <sys/time.h>
|
||||||
|
#endif
|
||||||
#ifndef NO_USER_BREAK_HANDLER
|
#ifndef NO_USER_BREAK_HANDLER
|
||||||
# include <signal.h>
|
# include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -200,8 +200,6 @@ static int do_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, vo
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
scheme_set_stack_base(PROMPT_STACK(stack_start), no_auto_statics);
|
scheme_set_stack_base(PROMPT_STACK(stack_start), no_auto_statics);
|
||||||
|
|
||||||
scheme_rktio = rktio_init();
|
|
||||||
|
|
||||||
return_code = _main(data);
|
return_code = _main(data);
|
||||||
|
|
||||||
|
@ -320,6 +318,7 @@ int scheme_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, void
|
||||||
{
|
{
|
||||||
scheme_setup_thread_local_key_if_needed();
|
scheme_setup_thread_local_key_if_needed();
|
||||||
scheme_init_os_thread();
|
scheme_init_os_thread();
|
||||||
|
scheme_rktio = rktio_init();
|
||||||
#ifdef MZ_USE_MZRT
|
#ifdef MZ_USE_MZRT
|
||||||
scheme_init_glib_log_queue();
|
scheme_init_glib_log_queue();
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -184,14 +184,24 @@ static void check_hello_content(rktio_t *rktio, char *fn)
|
||||||
|
|
||||||
static void wait_read(rktio_t *rktio, rktio_fd_t *fd)
|
static void wait_read(rktio_t *rktio, rktio_fd_t *fd)
|
||||||
{
|
{
|
||||||
rktio_poll_set_t *ps;
|
while (rktio_poll_read_ready(rktio, fd) == RKTIO_POLL_NOT_READY) {
|
||||||
ps = rktio_make_poll_set(rktio);
|
rktio_poll_set_t *ps;
|
||||||
check_valid(ps);
|
ps = rktio_make_poll_set(rktio);
|
||||||
rktio_poll_add(rktio, fd, ps, RKTIO_POLL_READ);
|
check_valid(ps);
|
||||||
rktio_sleep(rktio, 0, ps, NULL);
|
rktio_poll_add(rktio, fd, ps, RKTIO_POLL_READ);
|
||||||
rktio_poll_set_forget(rktio, ps);
|
rktio_sleep(rktio, 0, ps, NULL);
|
||||||
|
rktio_poll_set_forget(rktio, ps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* On Unix, we expect writing to a pipe to make the bytes
|
||||||
|
immediately available. On Windows, we expect a delay. */
|
||||||
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
|
# define PIPE_IMMEDIATELY_READY 1
|
||||||
|
#else
|
||||||
|
# define PIPE_IMMEDIATELY_READY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
static void check_read_write_pair(rktio_t *rktio, rktio_fd_t *fd, rktio_fd_t *fd2, int immediate_available)
|
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_t *lt;
|
||||||
|
@ -217,16 +227,16 @@ static void check_read_write_pair(rktio_t *rktio, rktio_fd_t *fd, rktio_fd_t *fd
|
||||||
|
|
||||||
/* Round-trip data through pipe: */
|
/* Round-trip data through pipe: */
|
||||||
if (rktio_fd_is_udp(rktio, fd2)) {
|
if (rktio_fd_is_udp(rktio, fd2)) {
|
||||||
amt = rktio_udp_sendto(rktio, fd2, NULL, "hello", 5);
|
amt = rktio_udp_sendto(rktio, fd2, NULL, "hola\n", 5);
|
||||||
} else
|
} else
|
||||||
amt = rktio_write(rktio, fd2, "hello", 5);
|
amt = rktio_write(rktio, fd2, "hola\n", 5);
|
||||||
check_valid(amt == 5);
|
check_valid(amt == 5);
|
||||||
|
|
||||||
if (!immediate_available) {
|
if (!immediate_available) {
|
||||||
/* Wait for read to be ready; should not block for long */
|
/* Wait for read to be ready; should not block for long */
|
||||||
wait_read(rktio, fd);
|
wait_read(rktio, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_valid(rktio_poll_read_ready(rktio, fd) == RKTIO_POLL_READY);
|
check_valid(rktio_poll_read_ready(rktio, fd) == RKTIO_POLL_READY);
|
||||||
if (lt) {
|
if (lt) {
|
||||||
check_ltps_read_ready(rktio, lt, h1);
|
check_ltps_read_ready(rktio, lt, h1);
|
||||||
|
@ -249,7 +259,7 @@ static void check_read_write_pair(rktio_t *rktio, rktio_fd_t *fd, rktio_fd_t *fd
|
||||||
} else
|
} else
|
||||||
amt = rktio_read(rktio, fd, buffer, sizeof(buffer));
|
amt = rktio_read(rktio, fd, buffer, sizeof(buffer));
|
||||||
check_valid(amt == 5);
|
check_valid(amt == 5);
|
||||||
check_valid(!strncmp(buffer, "hello", 5));
|
check_valid(!strncmp(buffer, "hola\n", 5));
|
||||||
check_valid(!rktio_poll_read_ready(rktio, fd));
|
check_valid(!rktio_poll_read_ready(rktio, fd));
|
||||||
|
|
||||||
/* Close pipe ends: */
|
/* Close pipe ends: */
|
||||||
|
@ -271,10 +281,11 @@ static void check_read_write_pair(rktio_t *rktio, rktio_fd_t *fd, rktio_fd_t *fd
|
||||||
#define AMOUNT_TO_WRITE_AND_BLOCK 1000000
|
#define AMOUNT_TO_WRITE_AND_BLOCK 1000000
|
||||||
#define AMOUNT_FOR_UDP 1000
|
#define AMOUNT_FOR_UDP 1000
|
||||||
|
|
||||||
static void check_fill_write(rktio_t *rktio, rktio_fd_t *fd2, rktio_addrinfo_t *dest_addr, intptr_t limit)
|
static void check_fill_write(rktio_t *rktio, rktio_fd_t *fd2, rktio_addrinfo_t *dest_addr, intptr_t limit, int verbose)
|
||||||
{
|
{
|
||||||
intptr_t i, amt;
|
intptr_t i, amt;
|
||||||
|
int r;
|
||||||
|
|
||||||
if (!limit)
|
if (!limit)
|
||||||
limit = AMOUNT_TO_WRITE_AND_BLOCK;
|
limit = AMOUNT_TO_WRITE_AND_BLOCK;
|
||||||
|
|
||||||
|
@ -287,13 +298,43 @@ static void check_fill_write(rktio_t *rktio, rktio_fd_t *fd2, rktio_addrinfo_t *
|
||||||
check_valid(amt != RKTIO_WRITE_ERROR);
|
check_valid(amt != RKTIO_WRITE_ERROR);
|
||||||
if (!amt)
|
if (!amt)
|
||||||
break;
|
break;
|
||||||
|
if (amt == RKTIO_WRITE_ERROR)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
check_valid(i > 0);
|
check_valid(i > 0);
|
||||||
if (!rktio_fd_is_udp(rktio, fd2))
|
if (!rktio_fd_is_udp(rktio, fd2))
|
||||||
check_valid(i < limit);
|
check_valid(i < limit);
|
||||||
|
if (verbose)
|
||||||
|
printf(" write full after %ld\n", (long)i);
|
||||||
|
|
||||||
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
|
if (rktio_fd_is_socket(rktio, fd2)) {
|
||||||
|
check_valid(rktio_poll_write_flushed(rktio, fd2) == RKTIO_POLL_READY);
|
||||||
|
} else {
|
||||||
|
/* pipe needs reader to count as flushed */
|
||||||
|
check_valid(rktio_poll_write_flushed(rktio, fd2) == RKTIO_POLL_NOT_READY);
|
||||||
|
{
|
||||||
|
/* Make sure that flushing doesn't claim to finish even if
|
||||||
|
we sleep for a while, because flushing on Windows means
|
||||||
|
data is received by the other end. */
|
||||||
|
rktio_poll_set_t *ps;
|
||||||
|
double start;
|
||||||
|
ps = rktio_make_poll_set(rktio);
|
||||||
|
check_valid(ps);
|
||||||
|
rktio_poll_add(rktio, fd2, ps, RKTIO_POLL_FLUSH);
|
||||||
|
start = rktio_get_inexact_milliseconds();
|
||||||
|
rktio_sleep(rktio, 0.1, ps, NULL);
|
||||||
|
check_valid(rktio_get_inexact_milliseconds() - start > 0.1);
|
||||||
|
rktio_poll_set_forget(rktio, ps);
|
||||||
|
check_valid(rktio_poll_write_flushed(rktio, fd2) == RKTIO_POLL_NOT_READY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
check_valid(rktio_poll_write_flushed(rktio, fd2) == RKTIO_POLL_READY);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_drain_read(rktio_t *rktio, rktio_fd_t *fd2, intptr_t limit)
|
static void check_drain_read(rktio_t *rktio, rktio_fd_t *fd2, intptr_t limit, int verbose)
|
||||||
{
|
{
|
||||||
intptr_t i, amt;
|
intptr_t i, amt;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
|
@ -311,6 +352,8 @@ static void check_drain_read(rktio_t *rktio, rktio_fd_t *fd2, intptr_t limit)
|
||||||
}
|
}
|
||||||
check_valid(i > 0);
|
check_valid(i > 0);
|
||||||
check_valid(i < limit);
|
check_valid(i < limit);
|
||||||
|
if (verbose)
|
||||||
|
printf(" read empty after %ld\n", (long)i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_many_lookup(rktio_t *rktio)
|
void check_many_lookup(rktio_t *rktio)
|
||||||
|
@ -329,7 +372,7 @@ void check_many_lookup(rktio_t *rktio)
|
||||||
check_valid(lookup[i]);
|
check_valid(lookup[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < LOOKUPS_N; j++) {
|
for (j = 0; j < LOOKUPS_N; ) {
|
||||||
ps = rktio_make_poll_set(rktio);
|
ps = rktio_make_poll_set(rktio);
|
||||||
check_valid(ps);
|
check_valid(ps);
|
||||||
|
|
||||||
|
@ -343,6 +386,7 @@ void check_many_lookup(rktio_t *rktio)
|
||||||
|
|
||||||
for (i = 0; i < LOOKUPS_N; i++) {
|
for (i = 0; i < LOOKUPS_N; i++) {
|
||||||
if (lookup[i] && (rktio_poll_addrinfo_lookup_ready(rktio, lookup[i]) == RKTIO_POLL_READY)) {
|
if (lookup[i] && (rktio_poll_addrinfo_lookup_ready(rktio, lookup[i]) == RKTIO_POLL_READY)) {
|
||||||
|
j++;
|
||||||
if ((i % 3) == 2)
|
if ((i % 3) == 2)
|
||||||
rktio_addrinfo_lookup_stop(rktio, lookup[i]);
|
rktio_addrinfo_lookup_stop(rktio, lookup[i]);
|
||||||
else {
|
else {
|
||||||
|
@ -351,7 +395,6 @@ void check_many_lookup(rktio_t *rktio)
|
||||||
rktio_addrinfo_free(rktio, addr);
|
rktio_addrinfo_free(rktio, addr);
|
||||||
}
|
}
|
||||||
lookup[i] = NULL;
|
lookup[i] = NULL;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,17 +406,20 @@ rktio_addrinfo_t *lookup_loop(rktio_t *rktio,
|
||||||
{
|
{
|
||||||
rktio_addrinfo_lookup_t *lookup;
|
rktio_addrinfo_lookup_t *lookup;
|
||||||
rktio_addrinfo_t *addr;
|
rktio_addrinfo_t *addr;
|
||||||
rktio_poll_set_t *ps;
|
|
||||||
|
|
||||||
ps = rktio_make_poll_set(rktio);
|
|
||||||
check_valid(ps);
|
|
||||||
|
|
||||||
lookup = rktio_start_addrinfo_lookup(rktio, hostname, portno, family, passive, tcp);
|
lookup = rktio_start_addrinfo_lookup(rktio, hostname, portno, family, passive, tcp);
|
||||||
check_valid(lookup);
|
check_valid(lookup);
|
||||||
|
|
||||||
rktio_poll_add_addrinfo_lookup(rktio, lookup, ps);
|
while (rktio_poll_addrinfo_lookup_ready(rktio, lookup) == RKTIO_POLL_NOT_READY) {
|
||||||
rktio_sleep(rktio, 0, ps, NULL);
|
rktio_poll_set_t *ps;
|
||||||
rktio_poll_set_forget(rktio, ps);
|
ps = rktio_make_poll_set(rktio);
|
||||||
|
check_valid(ps);
|
||||||
|
|
||||||
|
rktio_poll_add_addrinfo_lookup(rktio, lookup, ps);
|
||||||
|
rktio_sleep(rktio, 0, ps, NULL);
|
||||||
|
rktio_poll_set_forget(rktio, ps);
|
||||||
|
}
|
||||||
|
|
||||||
check_valid(rktio_poll_addrinfo_lookup_ready(rktio, lookup) == RKTIO_POLL_READY);
|
check_valid(rktio_poll_addrinfo_lookup_ready(rktio, lookup) == RKTIO_POLL_READY);
|
||||||
|
|
||||||
addr = rktio_addrinfo_lookup_get(rktio, lookup);
|
addr = rktio_addrinfo_lookup_get(rktio, lookup);
|
||||||
|
@ -408,12 +454,12 @@ static rktio_fd_t *connect_loop(rktio_t *rktio, rktio_addrinfo_t *addr, rktio_ad
|
||||||
{
|
{
|
||||||
rktio_connect_t *conn;
|
rktio_connect_t *conn;
|
||||||
rktio_poll_set_t *ps;
|
rktio_poll_set_t *ps;
|
||||||
rktio_fd_t *fd;
|
rktio_fd_t *fd = NULL;
|
||||||
|
|
||||||
conn = rktio_start_connect(rktio, addr, local_addr);
|
conn = rktio_start_connect(rktio, addr, local_addr);
|
||||||
check_valid(conn);
|
check_valid(conn);
|
||||||
|
|
||||||
while (1) {
|
while (!fd) {
|
||||||
ps = rktio_make_poll_set(rktio);
|
ps = rktio_make_poll_set(rktio);
|
||||||
check_valid(ps);
|
check_valid(ps);
|
||||||
|
|
||||||
|
@ -428,10 +474,10 @@ static rktio_fd_t *connect_loop(rktio_t *rktio, rktio_addrinfo_t *addr, rktio_ad
|
||||||
&& (rktio_get_last_error(rktio) == RKTIO_ERROR_CONNECT_TRYING_NEXT)) {
|
&& (rktio_get_last_error(rktio) == RKTIO_ERROR_CONNECT_TRYING_NEXT)) {
|
||||||
/* loop to try again */
|
/* loop to try again */
|
||||||
} else {
|
} else {
|
||||||
|
/* report other error: */
|
||||||
check_valid(fd);
|
check_valid(fd);
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
|
@ -541,9 +587,17 @@ int main(int argc, char **argv)
|
||||||
check_valid(perms != -1);
|
check_valid(perms != -1);
|
||||||
check_valid(perms & (RKTIO_PERMISSION_READ << 6));
|
check_valid(perms & (RKTIO_PERMISSION_READ << 6));
|
||||||
check_valid(perms & (RKTIO_PERMISSION_WRITE << 6));
|
check_valid(perms & (RKTIO_PERMISSION_WRITE << 6));
|
||||||
check_valid(rktio_set_file_or_directory_permissions(rktio, "test1", perms & (0x7 << 6)));
|
{
|
||||||
check_valid((perms & (0x7 << 6)) == rktio_get_file_or_directory_permissions(rktio, "test1", 1));
|
int ok;
|
||||||
rktio_set_file_or_directory_permissions(rktio, "test1", perms);
|
ok = rktio_set_file_or_directory_permissions(rktio, "test1", perms & (0x7 << 6));
|
||||||
|
if (ok
|
||||||
|
|| (RKTIO_ERROR_KIND_RACKET != rktio_get_last_error_kind(rktio))
|
||||||
|
|| (RKTIO_ERROR_BAD_PERMISSION != rktio_get_last_error(rktio))) {
|
||||||
|
check_valid(ok);
|
||||||
|
check_valid((perms & (0x7 << 6)) == rktio_get_file_or_directory_permissions(rktio, "test1", 1));
|
||||||
|
rktio_set_file_or_directory_permissions(rktio, "test1", perms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cp = rktio_copy_file_start(rktio, "test1a", "test1", 0);
|
cp = rktio_copy_file_start(rktio, "test1a", "test1", 0);
|
||||||
check_valid(cp);
|
check_valid(cp);
|
||||||
|
@ -638,7 +692,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
free(pipe_fds);
|
free(pipe_fds);
|
||||||
|
|
||||||
check_read_write_pair(rktio, fd, fd2, 1);
|
check_read_write_pair(rktio, fd, fd2, PIPE_IMMEDIATELY_READY);
|
||||||
|
|
||||||
/* Open pipe ends again: */
|
/* Open pipe ends again: */
|
||||||
pipe_fds = rktio_make_pipe(rktio, 0);
|
pipe_fds = rktio_make_pipe(rktio, 0);
|
||||||
|
@ -647,9 +701,12 @@ int main(int argc, char **argv)
|
||||||
fd2 = pipe_fds[1];
|
fd2 = pipe_fds[1];
|
||||||
free(pipe_fds);
|
free(pipe_fds);
|
||||||
|
|
||||||
check_fill_write(rktio, fd2, NULL, 0);
|
check_fill_write(rktio, fd2, NULL, 0, verbose);
|
||||||
check_drain_read(rktio, fd, 0);
|
if (!PIPE_IMMEDIATELY_READY)
|
||||||
|
wait_read(rktio, fd);
|
||||||
|
check_drain_read(rktio, fd, 0, verbose);
|
||||||
|
check_valid(rktio_poll_write_flushed(rktio, fd2) == RKTIO_POLL_READY);
|
||||||
|
|
||||||
check_valid(rktio_close(rktio, fd));
|
check_valid(rktio_close(rktio, fd));
|
||||||
check_valid(rktio_close(rktio, fd2));
|
check_valid(rktio_close(rktio, fd2));
|
||||||
}
|
}
|
||||||
|
@ -664,7 +721,7 @@ int main(int argc, char **argv)
|
||||||
rktio_listener_t *lnr;
|
rktio_listener_t *lnr;
|
||||||
|
|
||||||
check_many_lookup(rktio);
|
check_many_lookup(rktio);
|
||||||
|
|
||||||
addr = lookup_loop(rktio, NULL, 4536, -1, 1, 1);
|
addr = lookup_loop(rktio, NULL, 4536, -1, 1, 1);
|
||||||
|
|
||||||
lnr = rktio_listen(rktio, addr, 5, 1);
|
lnr = rktio_listen(rktio, addr, 5, 1);
|
||||||
|
@ -722,8 +779,10 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
fd2 = rktio_accept(rktio, lnr);
|
fd2 = rktio_accept(rktio, lnr);
|
||||||
|
|
||||||
check_fill_write(rktio, fd2, NULL, 0);
|
printf(" fill\n");
|
||||||
check_drain_read(rktio, fd, 0);
|
check_fill_write(rktio, fd2, NULL, 0, verbose);
|
||||||
|
printf(" drain\n");
|
||||||
|
check_drain_read(rktio, fd, 0, verbose);
|
||||||
|
|
||||||
check_valid(rktio_close(rktio, fd));
|
check_valid(rktio_close(rktio, fd));
|
||||||
check_valid(rktio_close(rktio, fd2));
|
check_valid(rktio_close(rktio, fd2));
|
||||||
|
@ -774,8 +833,8 @@ int main(int argc, char **argv)
|
||||||
addr = lookup_loop(rktio, "localhost", 4536, -1, 0, 0);
|
addr = lookup_loop(rktio, "localhost", 4536, -1, 0, 0);
|
||||||
check_valid(addr);
|
check_valid(addr);
|
||||||
|
|
||||||
check_fill_write(rktio, fd2, addr, AMOUNT_FOR_UDP);
|
check_fill_write(rktio, fd2, addr, AMOUNT_FOR_UDP, verbose);
|
||||||
check_drain_read(rktio, fd, AMOUNT_FOR_UDP+1);
|
check_drain_read(rktio, fd, AMOUNT_FOR_UDP+1, verbose);
|
||||||
|
|
||||||
rktio_addrinfo_free(rktio, addr);
|
rktio_addrinfo_free(rktio, addr);
|
||||||
rktio_addrinfo_free(rktio, intf_addr);
|
rktio_addrinfo_free(rktio, intf_addr);
|
||||||
|
@ -792,12 +851,18 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
rktio_status_t *status;
|
rktio_status_t *status;
|
||||||
rktio_process_result_t *result;
|
rktio_process_result_t *result;
|
||||||
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
char *argv[1] = { "/bin/cat" };
|
char *argv[1] = { "/bin/cat" };
|
||||||
|
int argc = 1;
|
||||||
|
#else
|
||||||
|
char *argv[3] = { "c:\\windows\\system32\\bash.exe", "-c", "cat" };
|
||||||
|
int argc = 3;
|
||||||
|
#endif
|
||||||
rktio_envvars_t *envvars = rktio_envvars(rktio);
|
rktio_envvars_t *envvars = rktio_envvars(rktio);
|
||||||
rktio_fd_t *err_fd = rktio_system_fd(rktio, 2, RKTIO_OPEN_WRITE);
|
rktio_fd_t *err_fd = rktio_std_fd(rktio, RKTIO_STDERR);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
result = rktio_process(rktio, argv[0], 1, argv,
|
result = rktio_process(rktio, argv[0], argc, argv,
|
||||||
NULL, NULL, err_fd,
|
NULL, NULL, err_fd,
|
||||||
pwd, envvars,
|
pwd, envvars,
|
||||||
0);
|
0);
|
||||||
|
@ -826,8 +891,14 @@ int main(int argc, char **argv)
|
||||||
rktio_process_forget(rktio, result->process);
|
rktio_process_forget(rktio, result->process);
|
||||||
free(result);
|
free(result);
|
||||||
|
|
||||||
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
|
# define CAN_INTERRUPT_NON_GROUP 1
|
||||||
|
#else
|
||||||
|
# define CAN_INTERRUPT_NON_GROUP 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Run and then break or kill `cat` */
|
/* Run and then break or kill `cat` */
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = (CAN_INTERRUPT_NON_GROUP ? 0 : 1); i < 2; i++) {
|
||||||
result = rktio_process(rktio, argv[0], 1, argv,
|
result = rktio_process(rktio, argv[0], 1, argv,
|
||||||
NULL, NULL, err_fd,
|
NULL, NULL, err_fd,
|
||||||
pwd, envvars,
|
pwd, envvars,
|
||||||
|
@ -852,7 +923,7 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
pause_for_process(rktio, result->process, dont_rely_on_sigchild);
|
pause_for_process(rktio, result->process, dont_rely_on_sigchild);
|
||||||
|
|
||||||
status = rktio_process_status(rktio, result->process);
|
status = rktio_process_status(rktio, result->process);
|
||||||
check_valid(status);
|
check_valid(status);
|
||||||
check_valid(!status->running);
|
check_valid(!status->running);
|
||||||
|
@ -862,8 +933,9 @@ int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char buffer[1];
|
char buffer[1];
|
||||||
intptr_t amt;
|
intptr_t amt;
|
||||||
|
wait_read(rktio, result->stdout_fd);
|
||||||
amt = rktio_read(rktio, result->stdout_fd, buffer, sizeof(buffer));
|
amt = rktio_read(rktio, result->stdout_fd, buffer, sizeof(buffer));
|
||||||
check_valid(amt == RKTIO_READ_EOF);
|
check_valid(amt == RKTIO_READ_EOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
check_valid(rktio_close(rktio, result->stdin_fd));
|
check_valid(rktio_close(rktio, result->stdin_fd));
|
||||||
|
@ -874,8 +946,18 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
char *argv[2] = { "/usr/bin/printenv", "RKTIO_EXAMPLE" };
|
char *argv[2] = { "/usr/bin/printenv", "RKTIO_EXAMPLE" };
|
||||||
|
int argc = 2;
|
||||||
|
int flags = 0;
|
||||||
|
int expect_crlf = 0;
|
||||||
|
#else
|
||||||
|
char *argv[2] = { "c:\\windows\\system32\\cmd.exe", "/c echo %RKTIO_EXAMPLE%" };
|
||||||
|
int argc = 2;
|
||||||
|
int flags = RKTIO_PROCESS_WINDOWS_EXACT_CMDLINE;
|
||||||
|
int expect_crlf = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf(" envvars\n");
|
printf(" envvars\n");
|
||||||
|
|
||||||
|
@ -886,10 +968,10 @@ int main(int argc, char **argv)
|
||||||
check_valid(!strcmp(s, "howdy"));
|
check_valid(!strcmp(s, "howdy"));
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
result = rktio_process(rktio, argv[0], 2, argv,
|
result = rktio_process(rktio, argv[0], argc, argv,
|
||||||
NULL, NULL, err_fd,
|
NULL, NULL, err_fd,
|
||||||
pwd, envvars,
|
pwd, envvars,
|
||||||
0);
|
flags);
|
||||||
check_valid(result);
|
check_valid(result);
|
||||||
|
|
||||||
/* Assume that a pipe can buffer the minimal output from `printenv`: */
|
/* Assume that a pipe can buffer the minimal output from `printenv`: */
|
||||||
|
@ -900,8 +982,13 @@ int main(int argc, char **argv)
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
intptr_t amt;
|
intptr_t amt;
|
||||||
amt = rktio_read(rktio, result->stdout_fd, buffer, sizeof(buffer));
|
amt = rktio_read(rktio, result->stdout_fd, buffer, sizeof(buffer));
|
||||||
check_valid(amt == 6);
|
if (expect_crlf) {
|
||||||
check_valid(!strncmp(buffer, "howdy\n", 6));
|
check_valid(amt == 7);
|
||||||
|
check_valid(!strncmp(buffer, "howdy\r\n", 7));
|
||||||
|
} else {
|
||||||
|
check_valid(amt == 6);
|
||||||
|
check_valid(!strncmp(buffer, "howdy\n", 6));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check_valid(rktio_close(rktio, result->stdin_fd));
|
check_valid(rktio_close(rktio, result->stdin_fd));
|
||||||
|
@ -919,7 +1006,11 @@ int main(int argc, char **argv)
|
||||||
/* Filesystem-change events */
|
/* Filesystem-change events */
|
||||||
|
|
||||||
if (rktio_fs_change_properties(rktio) & RKTIO_FS_CHANGE_SUPPORTED) {
|
if (rktio_fs_change_properties(rktio) & RKTIO_FS_CHANGE_SUPPORTED) {
|
||||||
char *path = "test1";
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
|
char *path = strdup("test1");
|
||||||
|
#else
|
||||||
|
char *path = rktio_get_current_directory(rktio);
|
||||||
|
#endif
|
||||||
rktio_fs_change_t *fc;
|
rktio_fs_change_t *fc;
|
||||||
rktio_poll_set_t *ps;
|
rktio_poll_set_t *ps;
|
||||||
rktio_ltps_t *lt;
|
rktio_ltps_t *lt;
|
||||||
|
@ -956,7 +1047,19 @@ int main(int argc, char **argv)
|
||||||
amt = rktio_write(rktio, fd2, "hola", 4);
|
amt = rktio_write(rktio, fd2, "hola", 4);
|
||||||
check_valid(amt == 4);
|
check_valid(amt == 4);
|
||||||
|
|
||||||
|
printf("wait...\n");
|
||||||
rktio_sleep(rktio, 0, ps, NULL);
|
rktio_sleep(rktio, 0, ps, NULL);
|
||||||
|
printf("done\n");
|
||||||
|
|
||||||
|
while (rktio_poll_fs_change_ready(rktio, fc) == RKTIO_POLL_NOT_READY) {
|
||||||
|
/* sleep woke up early - not what we want, but allowed by the spec */
|
||||||
|
rktio_poll_set_forget(rktio, ps);
|
||||||
|
ps = rktio_make_poll_set(rktio);
|
||||||
|
check_valid(ps);
|
||||||
|
rktio_poll_add_fs_change(rktio, fc, ps);
|
||||||
|
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);
|
||||||
check_valid(rktio_poll_fs_change_ready(rktio, fc) == RKTIO_POLL_READY);
|
check_valid(rktio_poll_fs_change_ready(rktio, fc) == RKTIO_POLL_READY);
|
||||||
|
|
||||||
|
@ -967,6 +1070,8 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
if (lt)
|
if (lt)
|
||||||
rktio_ltps_close(rktio, lt);
|
rktio_ltps_close(rktio, lt);
|
||||||
|
|
||||||
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
|
@ -1061,7 +1166,7 @@ int main(int argc, char **argv)
|
||||||
today->zone_offset, today->zone_offset / (60 * 60),
|
today->zone_offset, today->zone_offset / (60 * 60),
|
||||||
(today->is_dst ? ";DST" : ""),
|
(today->is_dst ? ";DST" : ""),
|
||||||
week_day_name(rktio, today->day_of_week),
|
week_day_name(rktio, today->day_of_week),
|
||||||
today->day, month_name(rktio, today->month), today->year,
|
today->day, month_name(rktio, today->month), (long)today->year,
|
||||||
today->day_of_year);
|
today->day_of_year);
|
||||||
|
|
||||||
if (today->zone_name)
|
if (today->zone_name)
|
||||||
|
|
5
racket/src/rktio/make32.bat
Normal file
5
racket/src/rktio/make32.bat
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
@echo off
|
||||||
|
echo ============================================
|
||||||
|
echo Assumes that the "librktio" project is built
|
||||||
|
echo ============================================
|
||||||
|
cl /I..\worksp\librktio demo.c ..\worksp\librktio\x32\Release\librktio.lib ws2_32.lib user32.lib shell32.lib
|
5
racket/src/rktio/make64.bat
Normal file
5
racket/src/rktio/make64.bat
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
@echo off
|
||||||
|
echo ============================================
|
||||||
|
echo Assumes that the "librktio" project is built
|
||||||
|
echo ============================================
|
||||||
|
cl /I..\worksp\librktio demo.c ..\worksp\librktio\x64\Release\librktio.lib ws2_32.lib user32.lib shell32.lib
|
|
@ -158,7 +158,7 @@ RKTIO_EXTERN rktio_fd_t *rktio_open(rktio_t *rktio, const char *src, int modes);
|
||||||
RKTIO_EXTERN rktio_ok_t rktio_close(rktio_t *rktio, rktio_fd_t *fd);
|
RKTIO_EXTERN rktio_ok_t rktio_close(rktio_t *rktio, rktio_fd_t *fd);
|
||||||
/* Can report `RKTIO_ERROR_EXISTS` in place of system error,
|
/* Can report `RKTIO_ERROR_EXISTS` in place of system error,
|
||||||
and can report `RKTIO_ERROR_UNSUPPORTED_TEXT_MODE` on Windows.
|
and can report `RKTIO_ERROR_UNSUPPORTED_TEXT_MODE` on Windows.
|
||||||
See also `rktio_write` and `rktio_poll_write_flushed. */
|
See also `rktio_write` and `rktio_poll_write_flushed`. */
|
||||||
|
|
||||||
RKTIO_EXTERN void rktio_close_noerr(rktio_t *rktio, rktio_fd_t *fd);
|
RKTIO_EXTERN void rktio_close_noerr(rktio_t *rktio, rktio_fd_t *fd);
|
||||||
/* The same as `rktio_close`, but without reporting errors. There's
|
/* The same as `rktio_close`, but without reporting errors. There's
|
||||||
|
@ -197,9 +197,9 @@ RKTIO_EXTERN intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *fd, const char *bu
|
||||||
mode. Alternatively, the result can be `RKTIO_WRITE_ERROR` for an
|
mode. Alternatively, the result can be `RKTIO_WRITE_ERROR` for an
|
||||||
error. Although rktio_write() is intended to write only bytes that
|
error. Although rktio_write() is intended to write only bytes that
|
||||||
can be fully delivered to the OS, there may be OS limitations that
|
can be fully delivered to the OS, there may be OS limitations that
|
||||||
require buffering (e.g., on Windows). Use
|
require buffering (e.g., on Windows). Use `rktio_poll_write_flushed`
|
||||||
rktio_poll_write_flushed() to make sure it's completely flushed
|
to make sure the data is received by the destination before closing
|
||||||
before closing. */
|
`fd`. */
|
||||||
|
|
||||||
#define RKTIO_WRITE_ERROR (-2)
|
#define RKTIO_WRITE_ERROR (-2)
|
||||||
|
|
||||||
|
@ -222,7 +222,10 @@ RKTIO_EXTERN rktio_tri_t rktio_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
#define RKTIO_POLL_ERROR (-2)
|
#define RKTIO_POLL_ERROR (-2)
|
||||||
|
|
||||||
RKTIO_EXTERN rktio_tri_t rktio_poll_write_flushed(rktio_t *rktio, rktio_fd_t *rfd);
|
RKTIO_EXTERN rktio_tri_t rktio_poll_write_flushed(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
/* See `rktio_write` above. */
|
/* See `rktio_write` above. Currently, the result is `RKTIO_POLL_NO_READY`
|
||||||
|
only on Windows, and only for a pipe or similar non-regular file.
|
||||||
|
A pipe counts as "flushed" when the other end has received the data
|
||||||
|
(because the sent data doesn't persist beyond closing the pipe). */
|
||||||
|
|
||||||
RKTIO_EXTERN rktio_tri_t rktio_file_lock_try(rktio_t *rktio, rktio_fd_t *rfd, int excl);
|
RKTIO_EXTERN rktio_tri_t rktio_file_lock_try(rktio_t *rktio, rktio_fd_t *rfd, int excl);
|
||||||
RKTIO_EXTERN rktio_ok_t rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd);
|
RKTIO_EXTERN rktio_ok_t rktio_file_unlock(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
|
@ -634,8 +637,9 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
RKTIO_EXTERN void rktio_sleep(rktio_t *rktio, float nsecs, rktio_poll_set_t *fds, rktio_ltps_t *lt);
|
RKTIO_EXTERN void rktio_sleep(rktio_t *rktio, float nsecs, rktio_poll_set_t *fds, rktio_ltps_t *lt);
|
||||||
/* Waits up to `nsecs` seconds (or forever if `nsecs` is 0) or until
|
/* Waits up to `nsecs` seconds (or forever if `nsecs` is 0), until
|
||||||
something registered with `fds` or `lt` is ready. */
|
something registered with `fds` or `lt` is ready, or until there's
|
||||||
|
some other activity that sometimes causes an early wakeup. */
|
||||||
|
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
/* Files, directories, and links */
|
/* Files, directories, and links */
|
||||||
|
|
|
@ -32,7 +32,7 @@ char **rktio_get_environ_array(void)
|
||||||
|
|
||||||
int rktio_is_ok_envvar_name(rktio_t *rktio, const char *s)
|
int rktio_is_ok_envvar_name(rktio_t *rktio, const char *s)
|
||||||
{
|
{
|
||||||
int i = strlen(s);
|
intptr_t i = strlen(s);
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
if (!s[0]) return 0;
|
if (!s[0]) return 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -159,8 +159,7 @@ rktio_envvars_t *rktio_envvars(rktio_t *rktio)
|
||||||
i = 0;
|
i = 0;
|
||||||
while (e[i]) {
|
while (e[i]) {
|
||||||
count++;
|
count++;
|
||||||
for (i = 0; e[i]; ) {
|
while (e[i]) i++;
|
||||||
}
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +170,8 @@ rktio_envvars_t *rktio_envvars(rktio_t *rktio)
|
||||||
envvars->vals = malloc(count * sizeof(char *));
|
envvars->vals = malloc(count * sizeof(char *));
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
for (i = 0; e[i]; ) {
|
i = 0;
|
||||||
|
while (e[i]) {
|
||||||
start = i;
|
start = i;
|
||||||
while (e[i]) { i++; }
|
while (e[i]) { i++; }
|
||||||
p = NARROW_PATH_copy(e + start);
|
p = NARROW_PATH_copy(e + start);
|
||||||
|
@ -182,6 +182,7 @@ rktio_envvars_t *rktio_envvars(rktio_t *rktio)
|
||||||
envvars->vals[count] = MSC_IZE(strdup)(p+j+1);
|
envvars->vals[count] = MSC_IZE(strdup)(p+j+1);
|
||||||
free(p);
|
free(p);
|
||||||
i++;
|
i++;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeEnvironmentStringsW(e);
|
FreeEnvironmentStringsW(e);
|
||||||
|
@ -382,7 +383,7 @@ void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars)
|
||||||
intptr_t len = 0, slen;
|
intptr_t len = 0, slen;
|
||||||
wchar_t *r, *s;
|
wchar_t *r, *s;
|
||||||
|
|
||||||
for (i = 0; i < envvars->count; i++) {
|
for (i = 0; i < envvars->count; i++) {
|
||||||
len += wcslen(WIDE_PATH_temp(envvars->names[i]));
|
len += wcslen(WIDE_PATH_temp(envvars->names[i]));
|
||||||
len += wcslen(WIDE_PATH_temp(envvars->vals[i]));
|
len += wcslen(WIDE_PATH_temp(envvars->vals[i]));
|
||||||
len += 2;
|
len += 2;
|
||||||
|
|
|
@ -115,7 +115,7 @@ const char *rktio_get_error_string(rktio_t *rktio, int kind, int errid)
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
else if (kind == RKTIO_ERROR_KIND_WINDOWS) {
|
else if (kind == RKTIO_ERROR_KIND_WINDOWS) {
|
||||||
wchar_t mbuf[256];
|
wchar_t mbuf[256];
|
||||||
int len, i;
|
intptr_t len, i;
|
||||||
if ((len = FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM
|
if ((len = FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM
|
||||||
| FORMAT_MESSAGE_IGNORE_INSERTS),
|
| FORMAT_MESSAGE_IGNORE_INSERTS),
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -128,7 +128,7 @@ const char *rktio_get_error_string(rktio_t *rktio, int kind, int errid)
|
||||||
mbuf[len] = 0;
|
mbuf[len] = 0;
|
||||||
es = NARROW_PATH_copy(mbuf);
|
es = NARROW_PATH_copy(mbuf);
|
||||||
/* Remove newlines: */
|
/* Remove newlines: */
|
||||||
for (i = strlen(s) - 1; i > 0; i--) {
|
for (i = strlen(es) - 1; i > 0; i--) {
|
||||||
if (isspace(es[i]))
|
if (isspace(es[i]))
|
||||||
es[i] = 0;
|
es[i] = 0;
|
||||||
else
|
else
|
||||||
|
|
|
@ -34,7 +34,7 @@ struct rktio_fd_t {
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
union {
|
union {
|
||||||
HANDLE fd;
|
HANDLE fd;
|
||||||
int sock; /* when `modes & RKTIO_OPEN_SOCKET` */
|
SOCKET sock; /* when `modes & RKTIO_OPEN_SOCKET` */
|
||||||
};
|
};
|
||||||
struct Win_FD_Input_Thread *th; /* input mode */
|
struct Win_FD_Input_Thread *th; /* input mode */
|
||||||
struct Win_FD_Output_Thread *oth; /* output mode */
|
struct Win_FD_Output_Thread *oth; /* output mode */
|
||||||
|
@ -53,11 +53,11 @@ struct rktio_fd_t {
|
||||||
typedef struct Win_FD_Input_Thread {
|
typedef struct Win_FD_Input_Thread {
|
||||||
/* This is malloced for use in a Win32 thread */
|
/* This is malloced for use in a Win32 thread */
|
||||||
HANDLE fd;
|
HANDLE fd;
|
||||||
volatile int avail, err, checking;
|
int avail, offset, err, checking, you_clean_up;
|
||||||
int *refcount;
|
int *refcount;
|
||||||
HANDLE eof;
|
HANDLE eof;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
HANDLE checking_sema, ready_sema, you_clean_up_sema;
|
HANDLE lock_sema, checking_sema, ready_sema;
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
} Win_FD_Input_Thread;
|
} Win_FD_Input_Thread;
|
||||||
|
|
||||||
|
@ -68,32 +68,38 @@ typedef struct Win_FD_Output_Thread {
|
||||||
works. We still use a thread to detect when the
|
works. We still use a thread to detect when the
|
||||||
write has ben flushed, which in turn is needed to
|
write has ben flushed, which in turn is needed to
|
||||||
know whether future writes will immediately succeed. */
|
know whether future writes will immediately succeed. */
|
||||||
volatile int flushed, needflush; /* Used for non-blocking, only. The flushed
|
int flushed, needflush; /* Used for non-blocking, only. The flushed
|
||||||
flag communicates from the flush-testing thread
|
flag communicates from the flush-testing thread
|
||||||
to the main thread. For efficiency, we request
|
to the main thread. For efficiency, we request
|
||||||
flush checking only when needed (instead of
|
flush checking only when needed (instead of
|
||||||
after every write); needflush indicates that
|
after every write); needflush indicates that
|
||||||
a flush check is currently needed, but hasn't
|
a flush check is currently needed, but hasn't
|
||||||
been started. */
|
been started. */
|
||||||
volatile int done, err_no;
|
int done, err_no, you_clean_up;
|
||||||
volatile unsigned int buflen, bufstart, bufend; /* used for blocking, only */
|
unsigned int buflen, bufstart, bufend; /* used for blocking, only */
|
||||||
unsigned char *buffer; /* used for blocking, only */
|
unsigned char *buffer; /* used for blocking, only */
|
||||||
int *refcount;
|
int *refcount;
|
||||||
HANDLE lock_sema, work_sema, ready_sema, you_clean_up_sema;
|
HANDLE lock_sema, work_sema, ready_sema;
|
||||||
/* lock_sema protects the fields, work_sema starts the flush or
|
|
||||||
flush-checking thread to work, ready_sema indicates that a flush
|
|
||||||
finished, and you_clean_up_sema is essentially a reference
|
|
||||||
count */
|
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
} Win_FD_Output_Thread;
|
} Win_FD_Output_Thread;
|
||||||
|
|
||||||
# define RKTIO_FD_BUFFSIZE 4096
|
# define RKTIO_FD_BUFFSIZE 4096
|
||||||
|
|
||||||
|
static void init_read_fd(rktio_t *rktio, rktio_fd_t *rfd);
|
||||||
|
static void deinit_read_fd(rktio_t *rktio, rktio_fd_t *rfd, int full_close);
|
||||||
|
static void deinit_write_fd(rktio_t *rktio, rktio_fd_t *rfd, int full_close);
|
||||||
|
|
||||||
|
static void deinit_fd(rktio_t *rktio, rktio_fd_t *rfd, int full_close)
|
||||||
|
{
|
||||||
|
deinit_read_fd(rktio, rfd, full_close);
|
||||||
|
deinit_write_fd(rktio, rfd, full_close);
|
||||||
|
}
|
||||||
|
|
||||||
static long WINAPI WindowsFDReader(Win_FD_Input_Thread *th);
|
static long WINAPI WindowsFDReader(Win_FD_Input_Thread *th);
|
||||||
static void WindowsFDICleanup(Win_FD_Input_Thread *th);
|
static void WindowsFDICleanup(Win_FD_Input_Thread *th, int close_mode);
|
||||||
|
|
||||||
static long WINAPI WindowsFDWriter(Win_FD_Output_Thread *oth);
|
static long WINAPI WindowsFDWriter(Win_FD_Output_Thread *oth);
|
||||||
static void WindowsFDOCleanup(Win_FD_Output_Thread *oth);
|
static void WindowsFDOCleanup(Win_FD_Output_Thread *oth, int close_mode);
|
||||||
|
|
||||||
typedef BOOL (WINAPI* CSI_proc)(HANDLE);
|
typedef BOOL (WINAPI* CSI_proc)(HANDLE);
|
||||||
|
|
||||||
|
@ -124,57 +130,6 @@ static intptr_t rktio_recount_output_text(const char *orig_buffer, const char *b
|
||||||
/* creating an fd */
|
/* creating an fd */
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
|
|
||||||
static void init_read_fd(rktio_t *rktio, rktio_fd_t *rfd)
|
|
||||||
{
|
|
||||||
#ifdef RKTIO_SYSTEM_UNIX
|
|
||||||
# ifdef SOME_FDS_ARE_NOT_SELECTABLE
|
|
||||||
rfd->bufcount = 0;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
|
||||||
if (!rktio_fd_is_regular_file(rktio, rfd)) {
|
|
||||||
/* To get non-blocking I/O for anything that can block, we create
|
|
||||||
a separate reader thread.
|
|
||||||
|
|
||||||
Yes, Windows NT pipes support non-blocking reads, but there
|
|
||||||
doesn't seem to be any way to use WaitForSingleObject to sleep
|
|
||||||
until characters are ready. PeekNamedPipe can be used for
|
|
||||||
polling, but not sleeping. */
|
|
||||||
|
|
||||||
Win_FD_Input_Thread *th;
|
|
||||||
DWORD id;
|
|
||||||
HANDLE h;
|
|
||||||
HANDLE sm;
|
|
||||||
char *bfr;
|
|
||||||
|
|
||||||
th = malloc(sizeof(Win_FD_Input_Thread));
|
|
||||||
rfd->th = th;
|
|
||||||
|
|
||||||
/* Replace buffer with a malloced one: */
|
|
||||||
bfr = malloc(RKTIO_FD_BUFFSIZE);
|
|
||||||
rfd->buffer = bfr;
|
|
||||||
th->buffer = (unsigned char *)bfr;
|
|
||||||
|
|
||||||
th->fd = rfd->fd;
|
|
||||||
th->avail = 0;
|
|
||||||
th->err = 0;
|
|
||||||
th->eof = NULL;
|
|
||||||
th->checking = 0;
|
|
||||||
|
|
||||||
sm = CreateSemaphore(NULL, 0, 1, NULL);
|
|
||||||
th->checking_sema = sm;
|
|
||||||
sm = CreateSemaphore(NULL, 0, 1, NULL);
|
|
||||||
th->ready_sema = sm;
|
|
||||||
sm = CreateSemaphore(NULL, 1, 1, NULL);
|
|
||||||
th->you_clean_up_sema = sm;
|
|
||||||
|
|
||||||
h = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)WindowsFDReader, th, 0, &id);
|
|
||||||
|
|
||||||
th->thread = h;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes)
|
rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes)
|
||||||
{
|
{
|
||||||
rktio_fd_t *rfd;
|
rktio_fd_t *rfd;
|
||||||
|
@ -200,7 +155,7 @@ rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes)
|
||||||
|
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
if (modes & RKTIO_OPEN_SOCKET)
|
if (modes & RKTIO_OPEN_SOCKET)
|
||||||
rfd->sock = system_fd;
|
rfd->sock = (SOCKET)system_fd;
|
||||||
else
|
else
|
||||||
rfd->fd = (HANDLE)system_fd;
|
rfd->fd = (HANDLE)system_fd;
|
||||||
if (!(modes & (RKTIO_OPEN_REGFILE | RKTIO_OPEN_NOT_REGFILE | RKTIO_OPEN_SOCKET))) {
|
if (!(modes & (RKTIO_OPEN_REGFILE | RKTIO_OPEN_NOT_REGFILE | RKTIO_OPEN_SOCKET))) {
|
||||||
|
@ -217,9 +172,6 @@ rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (modes & RKTIO_OPEN_READ)
|
|
||||||
init_read_fd(rktio, rfd);
|
|
||||||
|
|
||||||
if ((modes & RKTIO_OPEN_SOCKET) && (modes & RKTIO_OPEN_INIT))
|
if ((modes & RKTIO_OPEN_SOCKET) && (modes & RKTIO_OPEN_INIT))
|
||||||
rktio_socket_init(rktio, rfd);
|
rktio_socket_init(rktio, rfd);
|
||||||
|
|
||||||
|
@ -236,7 +188,7 @@ intptr_t rktio_fd_system_fd(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
#endif
|
#endif
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||||
return rfd->sock;
|
return (intptr_t)rfd->sock;
|
||||||
else
|
else
|
||||||
return (intptr_t)rfd->fd;
|
return (intptr_t)rfd->fd;
|
||||||
#endif
|
#endif
|
||||||
|
@ -262,7 +214,9 @@ rktio_fd_t *rktio_std_fd(rktio_t *rktio, int which)
|
||||||
which = STD_ERROR_HANDLE;
|
which = STD_ERROR_HANDLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return rktio_system_fd(rktio, (intptr_t)GetStdHandle(which), mode | RKTIO_OPEN_NOT_DIR);
|
return rktio_system_fd(rktio,
|
||||||
|
(intptr_t)GetStdHandle(which),
|
||||||
|
mode | RKTIO_OPEN_NOT_DIR);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,53 +354,8 @@ static rktio_ok_t do_close(rktio_t *rktio, rktio_fd_t *rfd, int set_error)
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||||
return rktio_socket_close(rktio, rfd, set_error);
|
return rktio_socket_close(rktio, rfd, set_error);
|
||||||
|
|
||||||
if (rfd->th) {
|
|
||||||
CSI_proc csi;
|
|
||||||
|
|
||||||
/* -1 for checking means "shut down" */
|
deinit_fd(rktio, rfd, 1);
|
||||||
rfd->th->checking = -1;
|
|
||||||
ReleaseSemaphore(rfd->th->checking_sema, 1, NULL);
|
|
||||||
|
|
||||||
if (rfd->th->eof && (rfd->th->eof != INVALID_HANDLE_VALUE)) {
|
|
||||||
ReleaseSemaphore(rfd->th->eof, 1, NULL);
|
|
||||||
rfd->th->eof = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
csi = get_csi();
|
|
||||||
if (csi) {
|
|
||||||
/* Helps thread wake up. Otherwise, it's possible for the
|
|
||||||
thread to stay stuck trying to read, in which case the
|
|
||||||
file handle (probably a pipe) doesn't get closed. */
|
|
||||||
csi(rfd->th->thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to get out of cleaning up the records (since they can't be
|
|
||||||
cleaned until the thread is also done: */
|
|
||||||
if (WaitForSingleObject(rfd->th->you_clean_up_sema, 0) != WAIT_OBJECT_0) {
|
|
||||||
/* The other thread exited and left us with clean-up: */
|
|
||||||
WindowsFDICleanup(rfd->th);
|
|
||||||
} /* otherwise, thread is responsible for clean-up */
|
|
||||||
}
|
|
||||||
if (rfd->oth) {
|
|
||||||
CSI_proc csi;
|
|
||||||
|
|
||||||
csi = get_csi();
|
|
||||||
|
|
||||||
if (csi) {
|
|
||||||
/* See also call to csi in fd_close_input */
|
|
||||||
csi(rfd->oth->thread);
|
|
||||||
}
|
|
||||||
CloseHandle(rfd->oth->thread);
|
|
||||||
rfd->oth->done = 1;
|
|
||||||
ReleaseSemaphore(rfd->oth->work_sema, 1, NULL);
|
|
||||||
|
|
||||||
/* Try to leave clean-up to the other thread: */
|
|
||||||
if (WaitForSingleObject(rfd->oth->you_clean_up_sema, 0) != WAIT_OBJECT_0) {
|
|
||||||
/* Other thread is already done, so we're stuck with clean-up: */
|
|
||||||
WindowsFDOCleanup(rfd->oth);
|
|
||||||
} /* otherwise, thread is responsible for clean-up */
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = 1;
|
ok = 1;
|
||||||
if (!rfd->th && !rfd->oth) {
|
if (!rfd->th && !rfd->oth) {
|
||||||
|
@ -476,6 +385,9 @@ void rktio_close_noerr(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
|
||||||
void rktio_forget(rktio_t *rktio, rktio_fd_t *rfd)
|
void rktio_forget(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
{
|
{
|
||||||
|
#ifdef RKTIO_WINDOWS_SYSTEM
|
||||||
|
deinit_fd(rktio, rfd, 1);
|
||||||
|
#endif
|
||||||
free(rfd);
|
free(rfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,7 +484,9 @@ int rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||||
return rktio_socket_poll_read_ready(rktio, rfd);
|
return rktio_socket_poll_read_ready(rktio, rfd);
|
||||||
|
|
||||||
|
init_read_fd(rktio, rfd);
|
||||||
|
|
||||||
if (!rfd->th) {
|
if (!rfd->th) {
|
||||||
/* No thread -- so wait works. This case isn't actually used
|
/* No thread -- so wait works. This case isn't actually used
|
||||||
right now, because wait doesn't seem to work reliably for
|
right now, because wait doesn't seem to work reliably for
|
||||||
|
@ -582,21 +496,21 @@ int rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
return RKTIO_POLL_READY;
|
return RKTIO_POLL_READY;
|
||||||
} else {
|
} else {
|
||||||
/* Has the reader thread pulled in data? */
|
/* Has the reader thread pulled in data? */
|
||||||
|
WaitForSingleObject(rfd->th->lock_sema, INFINITE);
|
||||||
if (rfd->th->checking) {
|
if (rfd->th->checking) {
|
||||||
/* The thread is still trying, last we knew. Check the
|
/* The thread is still trying.
|
||||||
data-is-ready sema: */
|
Clean up any signals that we may have ignored before. */
|
||||||
if (WaitForSingleObject(rfd->th->ready_sema, 0) == WAIT_OBJECT_0) {
|
WaitForSingleObject(rfd->th->ready_sema, 0);
|
||||||
rfd->th->checking = 0;
|
} else if (rfd->th->avail || rfd->th->err || rfd->th->eof) {
|
||||||
return RKTIO_POLL_READY;
|
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||||
}
|
|
||||||
} else if (rfd->th->avail || rfd->th->err || rfd->th->eof)
|
|
||||||
return RKTIO_POLL_READY; /* other thread found data */
|
return RKTIO_POLL_READY; /* other thread found data */
|
||||||
else {
|
} else {
|
||||||
/* Doesn't have anything, and it's not even looking. Tell it
|
/* Doesn't have anything, and it's not even looking. Tell it
|
||||||
to look: */
|
to look: */
|
||||||
rfd->th->checking = 1;
|
rfd->th->checking = 1;
|
||||||
ReleaseSemaphore(rfd->th->checking_sema, 1, NULL);
|
ReleaseSemaphore(rfd->th->checking_sema, 1, NULL);
|
||||||
}
|
}
|
||||||
|
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -647,11 +561,14 @@ int poll_write_ready_or_flushed(rktio_t *rktio, rktio_fd_t *rfd, int check_flush
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
if (rfd->modes & RKTIO_OPEN_SOCKET) {
|
||||||
|
if (check_flushed)
|
||||||
|
return RKTIO_POLL_READY;
|
||||||
return rktio_socket_poll_write_ready(rktio, rfd);
|
return rktio_socket_poll_write_ready(rktio, rfd);
|
||||||
|
}
|
||||||
|
|
||||||
if (rfd->oth) {
|
if (rfd->oth) {
|
||||||
/* Pipe output that can block... */
|
/* Pipe output that can block or needs a background flush */
|
||||||
int retval;
|
int retval;
|
||||||
Win_FD_Output_Thread *oth = rfd->oth;
|
Win_FD_Output_Thread *oth = rfd->oth;
|
||||||
|
|
||||||
|
@ -664,15 +581,27 @@ int poll_write_ready_or_flushed(rktio_t *rktio, rktio_fd_t *rfd, int check_flush
|
||||||
retval = 0;
|
retval = 0;
|
||||||
} else
|
} else
|
||||||
retval = oth->flushed;
|
retval = oth->flushed;
|
||||||
} else
|
if (!retval) {
|
||||||
retval = (oth->err_no || (check_flushed
|
/* While we hold the lock, clear any leftover notifications */
|
||||||
? !oth->buflen
|
WaitForSingleObject(oth->ready_sema, 0);
|
||||||
: (oth->buflen < RKTIO_FD_BUFFSIZE)));
|
}
|
||||||
if (!retval && !check_flushed)
|
} else {
|
||||||
WaitForSingleObject(oth->ready_sema, 0); /* clear any leftover state */
|
/* Using separate writing thread for Windows 95 */
|
||||||
|
if (oth->err_no) {
|
||||||
|
/* Delay error report until next write */
|
||||||
|
retval = 1;
|
||||||
|
} else
|
||||||
|
retval = (check_flushed
|
||||||
|
? !oth->buflen
|
||||||
|
: (oth->buflen < RKTIO_FD_BUFFSIZE));
|
||||||
|
if (!retval && !check_flushed) {
|
||||||
|
/* clear any leftover notifications */
|
||||||
|
WaitForSingleObject(oth->ready_sema, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
||||||
|
|
||||||
return retval;
|
return (retval ? RKTIO_POLL_READY : 0);
|
||||||
} else
|
} else
|
||||||
return RKTIO_POLL_READY; /* non-blocking output, such as a console, or haven't written yet */
|
return RKTIO_POLL_READY; /* non-blocking output, such as a console, or haven't written yet */
|
||||||
#endif
|
#endif
|
||||||
|
@ -709,30 +638,38 @@ void rktio_poll_add(rktio_t *rktio, rktio_fd_t *rfd, rktio_poll_set_t *fds, int
|
||||||
rktio_poll_set_t *fds2;
|
rktio_poll_set_t *fds2;
|
||||||
|
|
||||||
if (modes & RKTIO_POLL_READ) {
|
if (modes & RKTIO_POLL_READ) {
|
||||||
RKTIO_FD_SET(rfd->sock, fds);
|
RKTIO_FD_SET((intptr_t)rfd->sock, fds);
|
||||||
}
|
}
|
||||||
if (modes & RKTIO_POLL_WRITE) {
|
if (modes & RKTIO_POLL_WRITE) {
|
||||||
fds2 = RKTIO_GET_FDSET(fds, 1);
|
fds2 = RKTIO_GET_FDSET(fds, 1);
|
||||||
RKTIO_FD_SET(rfd->sock, fds2);
|
RKTIO_FD_SET((intptr_t)rfd->sock, fds2);
|
||||||
}
|
}
|
||||||
fds2 = RKTIO_GET_FDSET(fds, 2);
|
fds2 = RKTIO_GET_FDSET(fds, 2);
|
||||||
RKTIO_FD_SET(rfd->sock, fds2);
|
RKTIO_FD_SET((intptr_t)rfd->sock, fds2);
|
||||||
} else {
|
} else {
|
||||||
if (modes & RKTIO_POLL_READ) {
|
if (modes & RKTIO_POLL_READ) {
|
||||||
|
init_read_fd(rktio, rfd);
|
||||||
if (rfd->th) {
|
if (rfd->th) {
|
||||||
/* See fd_byte_ready */
|
WaitForSingleObject(rfd->th->lock_sema, INFINITE);
|
||||||
if (!rfd->th->checking) {
|
if (!rfd->th->checking) {
|
||||||
if (rfd->th->avail || rfd->th->err || rfd->th->eof) {
|
if (rfd->th->avail || rfd->th->err || rfd->th->eof) {
|
||||||
/* Data is ready. We shouldn't be trying to sleep, so force an
|
/* Data is ready. We shouldn't be trying to sleep, so force an
|
||||||
immediate wake-up: */
|
immediate wake-up: */
|
||||||
|
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||||
rktio_poll_set_add_nosleep(rktio, fds);
|
rktio_poll_set_add_nosleep(rktio, fds);
|
||||||
} else {
|
} else {
|
||||||
|
/* Ask the reader thread to start checking for data */
|
||||||
rfd->th->checking = 1;
|
rfd->th->checking = 1;
|
||||||
ReleaseSemaphore(rfd->th->checking_sema, 1, NULL);
|
ReleaseSemaphore(rfd->th->checking_sema, 1, NULL);
|
||||||
|
/* clear any notifications that we may have ignored before */
|
||||||
|
WaitForSingleObject(rfd->th->ready_sema, 0);
|
||||||
|
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||||
rktio_poll_set_add_handle(rktio, (intptr_t)rfd->th->ready_sema, fds, 1);
|
rktio_poll_set_add_handle(rktio, (intptr_t)rfd->th->ready_sema, fds, 1);
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
|
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||||
rktio_poll_set_add_handle(rktio, (intptr_t)rfd->th->ready_sema, fds, 1);
|
rktio_poll_set_add_handle(rktio, (intptr_t)rfd->th->ready_sema, fds, 1);
|
||||||
|
}
|
||||||
} else if (rktio_fd_is_regular_file(rktio, rfd)) {
|
} else if (rktio_fd_is_regular_file(rktio, rfd)) {
|
||||||
/* regular files never block */
|
/* regular files never block */
|
||||||
rktio_poll_set_add_nosleep(rktio, fds);
|
rktio_poll_set_add_nosleep(rktio, fds);
|
||||||
|
@ -827,7 +764,9 @@ intptr_t rktio_read_converted(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, int
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||||
return rktio_socket_read(rktio, rfd, buffer, len);
|
return rktio_socket_read(rktio, rfd, buffer, len);
|
||||||
|
|
||||||
|
init_read_fd(rktio, rfd);
|
||||||
|
|
||||||
if (!rfd->th) {
|
if (!rfd->th) {
|
||||||
/* We can read directly. This must be a regular file, where
|
/* We can read directly. This must be a regular file, where
|
||||||
reading never blocks. */
|
reading never blocks. */
|
||||||
|
@ -853,21 +792,28 @@ intptr_t rktio_read_converted(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, int
|
||||||
if (!rktio_poll_read_ready(rktio, rfd))
|
if (!rktio_poll_read_ready(rktio, rfd))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If we get this far, there's definitely data available.
|
/* If we get this far, there should be data available.
|
||||||
Extract data made available by the reader thread. */
|
Extract data made available by the reader thread. */
|
||||||
|
WaitForSingleObject(rfd->th->lock_sema, INFINITE);
|
||||||
if (rfd->th->eof) {
|
if (rfd->th->eof) {
|
||||||
if (rfd->th->eof != INVALID_HANDLE_VALUE) {
|
if (rfd->th->eof != INVALID_HANDLE_VALUE) {
|
||||||
ReleaseSemaphore(rfd->th->eof, 1, NULL);
|
ReleaseSemaphore(rfd->th->eof, 1, NULL);
|
||||||
rfd->th->eof = NULL;
|
rfd->th->eof = NULL;
|
||||||
}
|
}
|
||||||
|
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||||
return RKTIO_READ_EOF;
|
return RKTIO_READ_EOF;
|
||||||
} else if (rfd->th->err) {
|
} else if (rfd->th->err) {
|
||||||
|
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||||
set_windows_error(rfd->th->err);
|
set_windows_error(rfd->th->err);
|
||||||
return RKTIO_READ_ERROR;
|
return RKTIO_READ_ERROR;
|
||||||
} else {
|
} else {
|
||||||
intptr_t bc = rfd->th->avail;
|
intptr_t bc = rfd->th->avail;
|
||||||
rfd->th->avail = 0;
|
if (bc > len)
|
||||||
memcpy(buffer, rfd->buffer, bc);
|
bc = len;
|
||||||
|
rfd->th->avail -= bc;
|
||||||
|
memcpy(buffer, rfd->buffer + rfd->th->offset, bc);
|
||||||
|
rfd->th->offset += bc;
|
||||||
|
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||||
return bc;
|
return bc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -923,6 +869,88 @@ static intptr_t rktio_adjust_input_text(rktio_fd_t *rfd, char *buffer, char *is_
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void init_read_fd(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
{
|
||||||
|
if (!rktio_fd_is_regular_file(rktio, rfd) && !rfd->th) {
|
||||||
|
/* To get non-blocking I/O for anything that can block, we create
|
||||||
|
a separate reader thread.
|
||||||
|
|
||||||
|
Yes, Windows NT pipes support non-blocking reads, but there
|
||||||
|
doesn't seem to be any way to use WaitForSingleObject to sleep
|
||||||
|
until characters are ready. PeekNamedPipe can be used for
|
||||||
|
polling, but not sleeping. */
|
||||||
|
|
||||||
|
Win_FD_Input_Thread *th;
|
||||||
|
DWORD id;
|
||||||
|
HANDLE h;
|
||||||
|
HANDLE sm;
|
||||||
|
char *bfr;
|
||||||
|
|
||||||
|
th = calloc(1, sizeof(Win_FD_Input_Thread));
|
||||||
|
rfd->th = th;
|
||||||
|
|
||||||
|
bfr = malloc(RKTIO_FD_BUFFSIZE);
|
||||||
|
th->buffer = (unsigned char *)bfr;
|
||||||
|
rfd->buffer = bfr;
|
||||||
|
|
||||||
|
th->fd = rfd->fd;
|
||||||
|
th->avail = 0;
|
||||||
|
th->offset = 0;
|
||||||
|
th->err = 0;
|
||||||
|
th->eof = NULL;
|
||||||
|
th->checking = 0;
|
||||||
|
|
||||||
|
sm = CreateSemaphore(NULL, 1, 1, NULL);
|
||||||
|
th->lock_sema = sm;
|
||||||
|
sm = CreateSemaphore(NULL, 0, 1, NULL);
|
||||||
|
th->checking_sema = sm;
|
||||||
|
sm = CreateSemaphore(NULL, 0, 1, NULL);
|
||||||
|
th->ready_sema = sm;
|
||||||
|
|
||||||
|
h = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)WindowsFDReader, th, 0, &id);
|
||||||
|
|
||||||
|
th->thread = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deinit_read_fd(rktio_t *rktio, rktio_fd_t *rfd, int full_close)
|
||||||
|
{
|
||||||
|
if (rfd->th) {
|
||||||
|
CSI_proc csi;
|
||||||
|
|
||||||
|
WaitForSingleObject(rfd->th->lock_sema, INFINITE);
|
||||||
|
|
||||||
|
/* -1 for checking means "shut down" */
|
||||||
|
rfd->th->checking = -1;
|
||||||
|
ReleaseSemaphore(rfd->th->checking_sema, 1, NULL);
|
||||||
|
|
||||||
|
if (rfd->th->eof && (rfd->th->eof != INVALID_HANDLE_VALUE)) {
|
||||||
|
ReleaseSemaphore(rfd->th->eof, 1, NULL);
|
||||||
|
rfd->th->eof = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
csi = get_csi();
|
||||||
|
if (csi) {
|
||||||
|
/* Helps thread wake up. Otherwise, it's possible for the
|
||||||
|
thread to stay stuck trying to read, in which case the
|
||||||
|
file handle (probably a pipe) doesn't get closed. */
|
||||||
|
csi(rfd->th->thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get out of cleaning up the records (since they can't be
|
||||||
|
cleaned until the thread is also done: */
|
||||||
|
if (rfd->th->you_clean_up) {
|
||||||
|
/* The other thread exited and left us with clean-up: */
|
||||||
|
WindowsFDICleanup(rfd->th, (full_close ? 1 : -1));
|
||||||
|
} else {
|
||||||
|
/* otherwise, thread is responsible for clean-up */
|
||||||
|
rfd->th->you_clean_up = (full_close ? 1 : -1);
|
||||||
|
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static long WINAPI WindowsFDReader(Win_FD_Input_Thread *th)
|
static long WINAPI WindowsFDReader(Win_FD_Input_Thread *th)
|
||||||
{
|
{
|
||||||
DWORD toget, got;
|
DWORD toget, got;
|
||||||
|
@ -941,50 +969,75 @@ static long WINAPI WindowsFDReader(Win_FD_Input_Thread *th)
|
||||||
/* Wait until we're supposed to look for input: */
|
/* Wait until we're supposed to look for input: */
|
||||||
WaitForSingleObject(th->checking_sema, INFINITE);
|
WaitForSingleObject(th->checking_sema, INFINITE);
|
||||||
|
|
||||||
|
WaitForSingleObject(th->lock_sema, INFINITE);
|
||||||
if (th->checking < 0)
|
if (th->checking < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (ReadFile(th->fd, th->buffer, toget, &got, NULL)) {
|
if (th->avail) {
|
||||||
th->avail = got;
|
/* Spurious wake-up? */
|
||||||
if (!got) {
|
ReleaseSemaphore(th->lock_sema, 1, NULL);
|
||||||
/* We interpret a send of 0 bytes as a mid-stream EOF. */
|
|
||||||
eof_wait = CreateSemaphore(NULL, 0, 1, NULL);
|
|
||||||
th->eof = eof_wait;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
int err;
|
ReleaseSemaphore(th->lock_sema, 1, NULL);
|
||||||
err = GetLastError();
|
if (ReadFile(th->fd, th->buffer, toget, &got, NULL)) {
|
||||||
if (err == ERROR_BROKEN_PIPE) {
|
WaitForSingleObject(th->lock_sema, INFINITE);
|
||||||
th->eof = INVALID_HANDLE_VALUE;
|
th->avail = got;
|
||||||
perma_eof = 1;
|
th->offset = 0;
|
||||||
} else
|
if (!got) {
|
||||||
th->err = err;
|
/* We interpret a send of 0 bytes as a mid-stream EOF. */
|
||||||
}
|
eof_wait = CreateSemaphore(NULL, 0, 1, NULL);
|
||||||
|
th->eof = eof_wait;
|
||||||
|
}
|
||||||
|
/* lock is still held... */
|
||||||
|
} else {
|
||||||
|
int err;
|
||||||
|
err = GetLastError();
|
||||||
|
WaitForSingleObject(th->lock_sema, INFINITE);
|
||||||
|
if (err == ERROR_BROKEN_PIPE) {
|
||||||
|
th->eof = INVALID_HANDLE_VALUE;
|
||||||
|
perma_eof = 1;
|
||||||
|
} else
|
||||||
|
th->err = err;
|
||||||
|
/* lock is still held... */
|
||||||
|
}
|
||||||
|
|
||||||
/* Notify main program that we found something: */
|
th->checking = 0;
|
||||||
ReleaseSemaphore(th->ready_sema, 1, NULL);
|
|
||||||
|
|
||||||
if (eof_wait) {
|
/* Notify main program that we found something: */
|
||||||
WaitForSingleObject(eof_wait, INFINITE);
|
ReleaseSemaphore(th->ready_sema, 1, NULL);
|
||||||
eof_wait = NULL;
|
|
||||||
|
if (!perma_eof && !th->err) {
|
||||||
|
ReleaseSemaphore(th->lock_sema, 1, NULL);
|
||||||
|
|
||||||
|
if (eof_wait) {
|
||||||
|
WaitForSingleObject(eof_wait, INFINITE);
|
||||||
|
CloseHandle(eof_wait);
|
||||||
|
eof_wait = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* lock is still held on `break` out of loop */
|
||||||
|
|
||||||
/* We have to clean up if the main program has abandoned us: */
|
/* We have to clean up if the main program has abandoned us: */
|
||||||
if (WaitForSingleObject(th->you_clean_up_sema, 0) != WAIT_OBJECT_0) {
|
if (th->you_clean_up) {
|
||||||
WindowsFDICleanup(th);
|
WindowsFDICleanup(th, th->you_clean_up);
|
||||||
} /* otherwise, main program is responsible for clean-up */
|
} else {
|
||||||
|
/* otherwise, main program is responsible for clean-up */
|
||||||
|
th->you_clean_up = 1;
|
||||||
|
ReleaseSemaphore(th->lock_sema, 1, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WindowsFDICleanup(Win_FD_Input_Thread *th)
|
static void WindowsFDICleanup(Win_FD_Input_Thread *th, int close_mode)
|
||||||
{
|
{
|
||||||
|
CloseHandle(th->lock_sema);
|
||||||
CloseHandle(th->checking_sema);
|
CloseHandle(th->checking_sema);
|
||||||
CloseHandle(th->ready_sema);
|
CloseHandle(th->ready_sema);
|
||||||
CloseHandle(th->you_clean_up_sema);
|
|
||||||
|
|
||||||
CloseHandle(th->fd);
|
if (close_mode != -1)
|
||||||
|
CloseHandle(th->fd);
|
||||||
|
|
||||||
free(th->buffer);
|
free(th->buffer);
|
||||||
free(th);
|
free(th);
|
||||||
|
@ -1097,7 +1150,7 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
flushed). */
|
flushed). */
|
||||||
intptr_t out_len = 0;
|
intptr_t out_len = 0;
|
||||||
int ok, errsaved;
|
int ok, errsaved;
|
||||||
|
|
||||||
if (!rfd->oth || rfd->oth->nonblocking) {
|
if (!rfd->oth || rfd->oth->nonblocking) {
|
||||||
int nonblocking;
|
int nonblocking;
|
||||||
|
|
||||||
|
@ -1110,7 +1163,7 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
&& (GetFileType((HANDLE)rfd->fd) == FILE_TYPE_PIPE));
|
&& (GetFileType((HANDLE)rfd->fd) == FILE_TYPE_PIPE));
|
||||||
} else
|
} else
|
||||||
nonblocking = 1; /* must be, or we would not have gotten here */
|
nonblocking = 1; /* must be, or we would not have gotten here */
|
||||||
|
|
||||||
if (nonblocking) {
|
if (nonblocking) {
|
||||||
/* Unless we're still trying to flush old data, write to the
|
/* Unless we're still trying to flush old data, write to the
|
||||||
pipe and have the other thread start flushing it. */
|
pipe and have the other thread start flushing it. */
|
||||||
|
@ -1163,8 +1216,8 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
|| (!ok && (errsaved == ERROR_NOT_ENOUGH_MEMORY))) {
|
|| (!ok && (errsaved == ERROR_NOT_ENOUGH_MEMORY))) {
|
||||||
towrite = towrite >> 1;
|
towrite = towrite >> 1;
|
||||||
if (!towrite) {
|
if (!towrite) {
|
||||||
get_windows_error();
|
/* leave ok as 1 and winwrote as 0 */
|
||||||
return RKTIO_WRITE_ERROR;
|
break;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
|
@ -1177,32 +1230,42 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
out_len = winwrote;
|
out_len = winwrote;
|
||||||
|
} else {
|
||||||
|
/* Claim success for now to make `rfd->oth` get created,
|
||||||
|
and continuae non-blocking handling after that. */
|
||||||
|
ok = 1;
|
||||||
|
out_len = 1;
|
||||||
}
|
}
|
||||||
/* and create the writer thread... */
|
/* and create the writer thread... */
|
||||||
|
|
||||||
if (!rfd->oth) {
|
if (ok && (out_len > 0) && !rfd->oth) {
|
||||||
/* We create a thread even for pipes that can be put in
|
/* We create a thread even for pipes that can be put in
|
||||||
non-blocking mode, because that seems to be the only
|
non-blocking mode, because that seems to be the only
|
||||||
way to get evt behavior. */
|
way to get evt behavior of knowing that a write will
|
||||||
|
succeed because the previous content is flushed. */
|
||||||
Win_FD_Output_Thread *oth;
|
Win_FD_Output_Thread *oth;
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
DWORD id;
|
DWORD id;
|
||||||
unsigned char *bfr;
|
unsigned char *bfr;
|
||||||
HANDLE sm;
|
HANDLE sm;
|
||||||
|
|
||||||
oth = malloc(sizeof(Win_FD_Output_Thread));
|
oth = calloc(1, sizeof(Win_FD_Output_Thread));
|
||||||
rfd->oth = oth;
|
rfd->oth = oth;
|
||||||
|
|
||||||
oth->nonblocking = nonblocking;
|
oth->nonblocking = nonblocking;
|
||||||
|
|
||||||
if (!nonblocking) {
|
if (!nonblocking) {
|
||||||
|
/* Create the buffer to communicate with the writing thread. */
|
||||||
bfr = malloc(RKTIO_FD_BUFFSIZE);
|
bfr = malloc(RKTIO_FD_BUFFSIZE);
|
||||||
oth->buffer = bfr;
|
oth->buffer = bfr;
|
||||||
oth->flushed = 0;
|
oth->flushed = 0;
|
||||||
oth->needflush = 0;
|
oth->needflush = 0;
|
||||||
} else {
|
} else {
|
||||||
|
/* No buffer needed */
|
||||||
oth->buffer = NULL;
|
oth->buffer = NULL;
|
||||||
oth->flushed = 1;
|
/* Some data was written, so it's not yet flushed,
|
||||||
|
and we need a flush. */
|
||||||
|
oth->flushed = 0;
|
||||||
oth->needflush = 1;
|
oth->needflush = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1219,9 +1282,7 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
oth->work_sema = sm;
|
oth->work_sema = sm;
|
||||||
sm = CreateSemaphore(NULL, 1, 1, NULL);
|
sm = CreateSemaphore(NULL, 1, 1, NULL);
|
||||||
oth->ready_sema = sm;
|
oth->ready_sema = sm;
|
||||||
sm = CreateSemaphore(NULL, 1, 1, NULL);
|
|
||||||
oth->you_clean_up_sema = sm;
|
|
||||||
|
|
||||||
h = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)WindowsFDWriter, oth, 0, &id);
|
h = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE)WindowsFDWriter, oth, 0, &id);
|
||||||
|
|
||||||
oth->thread = h;
|
oth->thread = h;
|
||||||
|
@ -1231,7 +1292,7 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
/* We have a thread, if only to watch when the flush is
|
/* We have a thread, if only to watch when the flush is
|
||||||
done... */
|
done... */
|
||||||
|
|
||||||
if (!rfd->oth->nonblocking) {
|
if (rfd->oth && !rfd->oth->nonblocking) {
|
||||||
/* This case is for Win 95/98/Me anonymous pipes and
|
/* This case is for Win 95/98/Me anonymous pipes and
|
||||||
character devices. We haven't written anything yet! We
|
character devices. We haven't written anything yet! We
|
||||||
write to a buffer read by the other thread, and return --
|
write to a buffer read by the other thread, and return --
|
||||||
|
@ -1242,6 +1303,9 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
handle, same "device"), the port writes can get out of
|
handle, same "device"), the port writes can get out of
|
||||||
order. We try to avoid the problem by sleeping. */
|
order. We try to avoid the problem by sleeping. */
|
||||||
|
|
||||||
|
/* At this point, `out_len` is set ot 1, and we
|
||||||
|
need to set it to a value. */
|
||||||
|
|
||||||
Win_FD_Output_Thread *oth = rfd->oth;
|
Win_FD_Output_Thread *oth = rfd->oth;
|
||||||
|
|
||||||
WaitForSingleObject(oth->lock_sema, INFINITE);
|
WaitForSingleObject(oth->lock_sema, INFINITE);
|
||||||
|
@ -1249,7 +1313,8 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
errsaved = oth->err_no;
|
errsaved = oth->err_no;
|
||||||
ok = 0;
|
ok = 0;
|
||||||
} else if (oth->buflen == RKTIO_FD_BUFFSIZE) {
|
} else if (oth->buflen == RKTIO_FD_BUFFSIZE) {
|
||||||
WaitForSingleObject(oth->ready_sema, 0); /* clear any leftover state */
|
/* clear any leftover notifications */
|
||||||
|
WaitForSingleObject(oth->ready_sema, 0);
|
||||||
ok = 1;
|
ok = 1;
|
||||||
} else {
|
} else {
|
||||||
intptr_t topp;
|
intptr_t topp;
|
||||||
|
@ -1305,13 +1370,6 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
||||||
ok = 1;
|
ok = 1;
|
||||||
}
|
}
|
||||||
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
||||||
} else {
|
|
||||||
if (out_len > 0) {
|
|
||||||
/* We've already written, which implies that no flush is
|
|
||||||
in progress. We'll need a flush check in the future. */
|
|
||||||
rfd->oth->needflush = 1;
|
|
||||||
}
|
|
||||||
ok = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
|
@ -1373,23 +1431,54 @@ static intptr_t rktio_recount_output_text(const char *orig_buffer, const char *b
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void deinit_write_fd(rktio_t *rktio, rktio_fd_t *rfd, int full_close)
|
||||||
|
{
|
||||||
|
if (rfd->oth) {
|
||||||
|
CSI_proc csi;
|
||||||
|
|
||||||
|
WaitForSingleObject(rfd->oth->lock_sema, INFINITE);
|
||||||
|
|
||||||
|
csi = get_csi();
|
||||||
|
|
||||||
|
if (csi) {
|
||||||
|
/* See also call above */
|
||||||
|
csi(rfd->oth->thread);
|
||||||
|
}
|
||||||
|
CloseHandle(rfd->oth->thread);
|
||||||
|
rfd->oth->done = 1;
|
||||||
|
ReleaseSemaphore(rfd->oth->work_sema, 1, NULL);
|
||||||
|
|
||||||
|
/* Try to leave clean-up to the other thread: */
|
||||||
|
if (rfd->oth->you_clean_up) {
|
||||||
|
/* Other thread is already done, so we're stuck with clean-up: */
|
||||||
|
WindowsFDOCleanup(rfd->oth, (full_close ? 1 : -1));
|
||||||
|
} else {
|
||||||
|
/* otherwise, thread is responsible for clean-up */
|
||||||
|
rfd->oth->you_clean_up = (full_close ? 1 : -1);
|
||||||
|
ReleaseSemaphore(rfd->oth->lock_sema, 1, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static long WINAPI WindowsFDWriter(Win_FD_Output_Thread *oth)
|
static long WINAPI WindowsFDWriter(Win_FD_Output_Thread *oth)
|
||||||
{
|
{
|
||||||
DWORD towrite, wrote, start;
|
DWORD towrite, wrote, start;
|
||||||
int ok, more_work = 0, err_no;
|
int ok, more_work = 0, err_no;
|
||||||
|
|
||||||
if (oth->nonblocking) {
|
if (oth->nonblocking) {
|
||||||
/* Non-blocking mode (Win NT pipes). Just flush. */
|
/* Non-blocking mode (Win NT pipes). Just handle flush requests. */
|
||||||
|
WaitForSingleObject(oth->lock_sema, INFINITE);
|
||||||
while (!oth->done) {
|
while (!oth->done) {
|
||||||
|
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
||||||
WaitForSingleObject(oth->work_sema, INFINITE);
|
WaitForSingleObject(oth->work_sema, INFINITE);
|
||||||
|
|
||||||
FlushFileBuffers(oth->fd);
|
FlushFileBuffers(oth->fd);
|
||||||
|
|
||||||
WaitForSingleObject(oth->lock_sema, INFINITE);
|
WaitForSingleObject(oth->lock_sema, INFINITE);
|
||||||
oth->flushed = 1;
|
oth->flushed = 1;
|
||||||
ReleaseSemaphore(oth->ready_sema, 1, NULL);
|
ReleaseSemaphore(oth->ready_sema, 1, NULL);
|
||||||
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
|
||||||
}
|
}
|
||||||
|
/* lock held on loop exit */
|
||||||
} else {
|
} else {
|
||||||
/* Blocking mode. We do the writing work. This case is for
|
/* Blocking mode. We do the writing work. This case is for
|
||||||
Win 95/98/Me anonymous pipes and character devices (such
|
Win 95/98/Me anonymous pipes and character devices (such
|
||||||
|
@ -1398,14 +1487,15 @@ static long WINAPI WindowsFDWriter(Win_FD_Output_Thread *oth)
|
||||||
if (!more_work)
|
if (!more_work)
|
||||||
WaitForSingleObject(oth->work_sema, INFINITE);
|
WaitForSingleObject(oth->work_sema, INFINITE);
|
||||||
|
|
||||||
|
WaitForSingleObject(oth->lock_sema, INFINITE);
|
||||||
if (oth->done)
|
if (oth->done)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
WaitForSingleObject(oth->lock_sema, INFINITE);
|
|
||||||
towrite = oth->buflen;
|
towrite = oth->buflen;
|
||||||
if (towrite > (RKTIO_FD_BUFFSIZE - oth->bufstart))
|
if (towrite > (RKTIO_FD_BUFFSIZE - oth->bufstart))
|
||||||
towrite = RKTIO_FD_BUFFSIZE - oth->bufstart;
|
towrite = RKTIO_FD_BUFFSIZE - oth->bufstart;
|
||||||
start = oth->bufstart;
|
start = oth->bufstart;
|
||||||
|
|
||||||
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
||||||
|
|
||||||
ok = WriteFile(oth->fd, oth->buffer + start, towrite, &wrote, NULL);
|
ok = WriteFile(oth->fd, oth->buffer + start, towrite, &wrote, NULL);
|
||||||
|
@ -1428,21 +1518,27 @@ static long WINAPI WindowsFDWriter(Win_FD_Output_Thread *oth)
|
||||||
ReleaseSemaphore(oth->ready_sema, 1, NULL);
|
ReleaseSemaphore(oth->ready_sema, 1, NULL);
|
||||||
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
||||||
}
|
}
|
||||||
|
/* lock is still held on `break` out of loop */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oth->you_clean_up) {
|
||||||
|
WindowsFDOCleanup(oth, oth->you_clean_up);
|
||||||
|
} else {
|
||||||
|
/* otherwise, main thread is responsible for clean-up */
|
||||||
|
oth->you_clean_up = 1;
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void WindowsFDOCleanup(Win_FD_Output_Thread *oth)
|
static void WindowsFDOCleanup(Win_FD_Output_Thread *oth, int close_mode)
|
||||||
{
|
{
|
||||||
CloseHandle(oth->lock_sema);
|
CloseHandle(oth->lock_sema);
|
||||||
CloseHandle(oth->work_sema);
|
CloseHandle(oth->work_sema);
|
||||||
CloseHandle(oth->you_clean_up_sema);
|
|
||||||
|
if (close_mode != -1)
|
||||||
CloseHandle(oth->fd);
|
CloseHandle(oth->fd);
|
||||||
|
|
||||||
if (oth->buffer)
|
if (oth->buffer)
|
||||||
free(oth->buffer);
|
free(oth->buffer);
|
||||||
|
|
|
@ -81,7 +81,7 @@ static rktio_fd_t *open_read(rktio_t *rktio, const char *filename, int modes)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfd = rktio_system_fd(rktio, (intptr_t)fd, RKTIO_OPEN_READ);
|
rfd = rktio_system_fd(rktio, (intptr_t)fd, RKTIO_OPEN_READ | RKTIO_OPEN_NOT_DIR);
|
||||||
|
|
||||||
if (modes & RKTIO_OPEN_TEXT) {
|
if (modes & RKTIO_OPEN_TEXT) {
|
||||||
if (!rktio_fd_is_regular_file(rktio, rfd)) {
|
if (!rktio_fd_is_regular_file(rktio, rfd)) {
|
||||||
|
@ -228,7 +228,7 @@ static rktio_fd_t *open_write(rktio_t *rktio, const char *filename, int modes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rfd = rktio_system_fd(rktio, (intptr_t)fd, modes | RKTIO_OPEN_NOT_DIR);
|
rfd = rktio_system_fd(rktio, (intptr_t)fd, modes);
|
||||||
|
|
||||||
if (rktio_fd_is_directory(rktio, rfd)) {
|
if (rktio_fd_is_directory(rktio, rfd)) {
|
||||||
rktio_close(rktio, rfd);
|
rktio_close(rktio, rfd);
|
||||||
|
@ -244,8 +244,12 @@ static rktio_fd_t *open_write(rktio_t *rktio, const char *filename, int modes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((modes & RKTIO_OPEN_APPEND) && rktio_fd_is_regular_file(rktio, rfd)) {
|
if ((modes & (RKTIO_OPEN_APPEND |RKTIO_OPEN_TRUNCATE))
|
||||||
SetFilePointer(fd, 0, NULL, FILE_END);
|
&& rktio_fd_is_regular_file(rktio, rfd)) {
|
||||||
|
if (modes & RKTIO_OPEN_APPEND)
|
||||||
|
SetFilePointer(fd, 0, NULL, FILE_END);
|
||||||
|
else
|
||||||
|
SetEndOfFile(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rfd;
|
return rfd;
|
||||||
|
|
|
@ -669,7 +669,7 @@ int rktio_set_current_directory(rktio_t *rktio, const char *path)
|
||||||
static rktio_identity_t *get_identity(rktio_t *rktio, rktio_fd_t *fd, const char *path, int follow_links)
|
static rktio_identity_t *get_identity(rktio_t *rktio, rktio_fd_t *fd, const char *path, int follow_links)
|
||||||
{
|
{
|
||||||
uintptr_t devi = 0, inoi = 0, inoi2 = 0;
|
uintptr_t devi = 0, inoi = 0, inoi2 = 0;
|
||||||
uintptr_t devi_bits = 0, inoi_bits = 0, inoi2_bits = 0;
|
int devi_bits = 0, inoi_bits = 0, inoi2_bits = 0;
|
||||||
|
|
||||||
#ifdef RKTIO_SYSTEM_UNIX
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
int errid = 0;
|
int errid = 0;
|
||||||
|
@ -830,6 +830,9 @@ int rktio_rename_file(rktio_t *rktio, const char *dest, const char *src, int exi
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
get_windows_error();
|
get_windows_error();
|
||||||
|
} else if (errid == ERROR_ALREADY_EXISTS) {
|
||||||
|
set_racket_error(RKTIO_ERROR_EXISTS);
|
||||||
|
return 0;
|
||||||
} else
|
} else
|
||||||
get_windows_error();
|
get_windows_error();
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#define RKTIO_SHUT_RD SHUT_RD
|
#define RKTIO_SHUT_RD SHUT_RD
|
||||||
#define RKTIO_SHUT_WR SHUT_WR
|
#define RKTIO_SHUT_WR SHUT_WR
|
||||||
|
|
||||||
|
#define RKTIO_SOCKS(s) s
|
||||||
|
|
||||||
typedef intptr_t rktio_socket_t;
|
typedef intptr_t rktio_socket_t;
|
||||||
typedef unsigned int rktio_sockopt_len_t;
|
typedef unsigned int rktio_sockopt_len_t;
|
||||||
|
|
||||||
|
@ -81,6 +83,9 @@ struct SOCKADDR_IN {
|
||||||
typedef SOCKET rktio_socket_t;
|
typedef SOCKET rktio_socket_t;
|
||||||
typedef int rktio_sockopt_len_t;
|
typedef int rktio_sockopt_len_t;
|
||||||
|
|
||||||
|
/* Avoid warnings, since select() first argument is ignored: */
|
||||||
|
#define RKTIO_SOCKS(s) 0
|
||||||
|
|
||||||
typedef struct SOCKADDR_IN rktio_unspec_address;
|
typedef struct SOCKADDR_IN rktio_unspec_address;
|
||||||
# define REGISTER_SOCKET(s) winsock_remember(s)
|
# define REGISTER_SOCKET(s) winsock_remember(s)
|
||||||
# define UNREGISTER_SOCKET(s) winsock_forget(s)
|
# define UNREGISTER_SOCKET(s) winsock_forget(s)
|
||||||
|
@ -858,9 +863,14 @@ void rktio_winsock_done(rktio_t *rktio)
|
||||||
/* TCP sockets */
|
/* TCP sockets */
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
|
|
||||||
|
rktio_socket_t rktio_fd_socket(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
{
|
||||||
|
return (rktio_socket_t)rktio_fd_system_fd(rktio, rfd);
|
||||||
|
}
|
||||||
|
|
||||||
void rktio_socket_init(rktio_t *rktio, rktio_fd_t *rfd)
|
void rktio_socket_init(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
|
|
||||||
#ifdef RKTIO_SYSTEM_UNIX
|
#ifdef RKTIO_SYSTEM_UNIX
|
||||||
fcntl(s, F_SETFL, RKTIO_NONBLOCKING);
|
fcntl(s, F_SETFL, RKTIO_NONBLOCKING);
|
||||||
|
@ -901,7 +911,7 @@ int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd, int set_error)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
int err;
|
int err;
|
||||||
UNREGISTER_SOCKET(s);
|
UNREGISTER_SOCKET(s);
|
||||||
err = closesocket(s);
|
err = closesocket(s);
|
||||||
|
@ -916,7 +926,7 @@ int rktio_socket_close(rktio_t *rktio, rktio_fd_t *rfd, int set_error)
|
||||||
void rktio_socket_own(rktio_t *rktio, rktio_fd_t *rfd)
|
void rktio_socket_own(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
{
|
{
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
REGISTER_SOCKET(s);
|
REGISTER_SOCKET(s);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -924,14 +934,14 @@ void rktio_socket_own(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
void rktio_socket_forget_owned(rktio_t *rktio, rktio_fd_t *rfd)
|
void rktio_socket_forget_owned(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
{
|
{
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
UNREGISTER_SOCKET(s);
|
UNREGISTER_SOCKET(s);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int rktio_socket_shutdown(rktio_t *rktio, rktio_fd_t *rfd, int mode)
|
int rktio_socket_shutdown(rktio_t *rktio, rktio_fd_t *rfd, int mode)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
|
|
||||||
if (shutdown(s, ((mode == RKTIO_SHUTDOWN_READ) ? RKTIO_SHUT_RD : RKTIO_SHUT_WR))) {
|
if (shutdown(s, ((mode == RKTIO_SHUTDOWN_READ) ? RKTIO_SHUT_RD : RKTIO_SHUT_WR))) {
|
||||||
get_socket_error();
|
get_socket_error();
|
||||||
|
@ -948,7 +958,7 @@ int rktio_socket_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
#endif
|
#endif
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
DECL_SOCK_FDSET(writefds);
|
DECL_SOCK_FDSET(writefds);
|
||||||
DECL_SOCK_FDSET(exnfds);
|
DECL_SOCK_FDSET(exnfds);
|
||||||
struct timeval time = {0, 0};
|
struct timeval time = {0, 0};
|
||||||
|
@ -962,7 +972,7 @@ int rktio_socket_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
RKTIO_SOCK_FD_ZERO(exnfds);
|
RKTIO_SOCK_FD_ZERO(exnfds);
|
||||||
RKTIO_SOCK_FD_SET(s, exnfds);
|
RKTIO_SOCK_FD_SET(s, exnfds);
|
||||||
|
|
||||||
sr = select(s + 1, NULL, writefds, exnfds, &time);
|
sr = select(RKTIO_SOCKS(s + 1), NULL, writefds, exnfds, &time);
|
||||||
|
|
||||||
if (sr == -1) {
|
if (sr == -1) {
|
||||||
get_socket_error();
|
get_socket_error();
|
||||||
|
@ -982,7 +992,7 @@ int rktio_socket_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
#endif
|
#endif
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
DECL_SOCK_FDSET(readfds);
|
DECL_SOCK_FDSET(readfds);
|
||||||
DECL_SOCK_FDSET(exnfds);
|
DECL_SOCK_FDSET(exnfds);
|
||||||
struct timeval time = {0, 0};
|
struct timeval time = {0, 0};
|
||||||
|
@ -996,7 +1006,7 @@ int rktio_socket_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
RKTIO_SOCK_FD_ZERO(exnfds);
|
RKTIO_SOCK_FD_ZERO(exnfds);
|
||||||
RKTIO_SOCK_FD_SET(s, exnfds);
|
RKTIO_SOCK_FD_SET(s, exnfds);
|
||||||
|
|
||||||
sr = select(s + 1, readfds, NULL, exnfds, &time);
|
sr = select(RKTIO_SOCKS(s + 1), readfds, NULL, exnfds, &time);
|
||||||
|
|
||||||
if (sr == -1) {
|
if (sr == -1) {
|
||||||
get_socket_error();
|
get_socket_error();
|
||||||
|
@ -1015,7 +1025,7 @@ rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
return rktio_dup(rktio, rfd);
|
return rktio_dup(rktio, rfd);
|
||||||
#endif
|
#endif
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
rktio_socket_t nsocket;
|
rktio_socket_t nsocket;
|
||||||
intptr_t rc;
|
intptr_t rc;
|
||||||
WSAPROTOCOL_INFO protocolInfo;
|
WSAPROTOCOL_INFO protocolInfo;
|
||||||
|
@ -1035,7 +1045,7 @@ rktio_fd_t *rktio_socket_dup(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
|
||||||
intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
intptr_t rktio_socket_read(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
int rn;
|
int rn;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -1061,7 +1071,7 @@ static intptr_t do_socket_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buf
|
||||||
/* for UDP sendto: */
|
/* for UDP sendto: */
|
||||||
rktio_addrinfo_t *addr)
|
rktio_addrinfo_t *addr)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
intptr_t sent;
|
intptr_t sent;
|
||||||
int errid = 0;
|
int errid = 0;
|
||||||
|
|
||||||
|
@ -1183,7 +1193,9 @@ static rktio_connect_t *try_connect(rktio_t *rktio, rktio_connect_t *conn)
|
||||||
errno = status;
|
errno = status;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
conn->trying_fd = rktio_system_fd(rktio, s, RKTIO_OPEN_SOCKET | RKTIO_OPEN_READ | RKTIO_OPEN_WRITE | RKTIO_OPEN_OWN);
|
conn->trying_fd = rktio_system_fd(rktio,
|
||||||
|
(intptr_t)s,
|
||||||
|
RKTIO_OPEN_SOCKET | RKTIO_OPEN_READ | RKTIO_OPEN_WRITE | RKTIO_OPEN_OWN);
|
||||||
conn->inprogress = inprogress;
|
conn->inprogress = inprogress;
|
||||||
|
|
||||||
return conn;
|
return conn;
|
||||||
|
@ -1223,7 +1235,7 @@ rktio_fd_t *rktio_connect_finish(rktio_t *rktio, rktio_connect_t *conn)
|
||||||
/* Check whether connect succeeded, or get error: */
|
/* Check whether connect succeeded, or get error: */
|
||||||
int errid;
|
int errid;
|
||||||
rktio_sockopt_len_t so_len = sizeof(errid);
|
rktio_sockopt_len_t so_len = sizeof(errid);
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void *)&errid, &so_len) != 0) {
|
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (void *)&errid, &so_len) != 0) {
|
||||||
errid = SOCK_ERRNO();
|
errid = SOCK_ERRNO();
|
||||||
} else
|
} else
|
||||||
|
@ -1541,7 +1553,7 @@ static int do_poll_accept_ready(rktio_t *rktio, rktio_listener_t *listener, int
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
sr = select(mx + 1, RKTIO_SOCK_FDS(readfds), NULL, RKTIO_SOCK_FDS(exnfds), &time);
|
sr = select(RKTIO_SOCKS(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 (sr > 0) {
|
||||||
|
@ -1579,8 +1591,8 @@ void rktio_poll_add_accept(rktio_t *rktio, rktio_listener_t *listener, rktio_pol
|
||||||
|
|
||||||
for (i = 0; i < listener->count; i++) {
|
for (i = 0; i < listener->count; i++) {
|
||||||
s = listener->s[i];
|
s = listener->s[i];
|
||||||
RKTIO_FD_SET(s, fds);
|
RKTIO_FD_SET((intptr_t)s, fds);
|
||||||
RKTIO_FD_SET(s, fds2);
|
RKTIO_FD_SET((intptr_t)s, fds2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1660,7 +1672,7 @@ char **rktio_socket_address(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
rktio_sockopt_len_t name_len;
|
rktio_sockopt_len_t name_len;
|
||||||
|
|
||||||
name_len = sizeof(name);
|
name_len = sizeof(name);
|
||||||
if (getsockname(rktio_fd_system_fd(rktio, rfd), (struct sockaddr *)name, &name_len)) {
|
if (getsockname(rktio_fd_socket(rktio, rfd), (struct sockaddr *)name, &name_len)) {
|
||||||
get_socket_error();
|
get_socket_error();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1674,7 +1686,7 @@ char **rktio_socket_peer_address(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
rktio_sockopt_len_t name_len;
|
rktio_sockopt_len_t name_len;
|
||||||
|
|
||||||
name_len = sizeof(name);
|
name_len = sizeof(name);
|
||||||
if (getpeername(rktio_fd_system_fd(rktio, rfd), (struct sockaddr *)name, &name_len)) {
|
if (getpeername(rktio_fd_socket(rktio, rfd), (struct sockaddr *)name, &name_len)) {
|
||||||
get_socket_error();
|
get_socket_error();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1727,7 +1739,7 @@ rktio_fd_t *rktio_udp_open(rktio_t *rktio, rktio_addrinfo_t *addr, int family)
|
||||||
|
|
||||||
int rktio_udp_disconnect(rktio_t *rktio, rktio_fd_t *rfd)
|
int rktio_udp_disconnect(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
#ifdef USE_NULL_TO_DISCONNECT_UDP
|
#ifdef USE_NULL_TO_DISCONNECT_UDP
|
||||||
|
@ -1757,7 +1769,7 @@ int rktio_udp_disconnect(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
|
||||||
int rktio_udp_bind(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr, rktio_bool_t reuse)
|
int rktio_udp_bind(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr, rktio_bool_t reuse)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (reuse) {
|
if (reuse) {
|
||||||
|
@ -1782,7 +1794,7 @@ int rktio_udp_bind(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr, rkti
|
||||||
|
|
||||||
int rktio_udp_connect(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr)
|
int rktio_udp_connect(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *addr)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* connect using first address that works: */
|
/* connect using first address that works: */
|
||||||
|
@ -1804,7 +1816,7 @@ intptr_t rktio_udp_sendto(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *add
|
||||||
|
|
||||||
rktio_length_and_addrinfo_t *rktio_udp_recvfrom(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
rktio_length_and_addrinfo_t *rktio_udp_recvfrom(rktio_t *rktio, rktio_fd_t *rfd, char *buffer, intptr_t len)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
rktio_length_and_addrinfo_t *r;
|
rktio_length_and_addrinfo_t *r;
|
||||||
int rn, errid;
|
int rn, errid;
|
||||||
char src_addr[RKTIO_SOCK_NAME_MAX_LEN];
|
char src_addr[RKTIO_SOCK_NAME_MAX_LEN];
|
||||||
|
@ -1855,7 +1867,7 @@ rktio_length_and_addrinfo_t *rktio_udp_recvfrom(rktio_t *rktio, rktio_fd_t *rfd,
|
||||||
|
|
||||||
int rktio_udp_get_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd)
|
int rktio_udp_get_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
u_char loop;
|
u_char loop;
|
||||||
rktio_sockopt_len_t loop_len = sizeof(loop);
|
rktio_sockopt_len_t loop_len = sizeof(loop);
|
||||||
int status;
|
int status;
|
||||||
|
@ -1871,7 +1883,7 @@ 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)
|
int rktio_udp_set_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd, int on)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
u_char loop = (on ? 1 : 0);
|
u_char loop = (on ? 1 : 0);
|
||||||
rktio_sockopt_len_t loop_len = sizeof(loop);
|
rktio_sockopt_len_t loop_len = sizeof(loop);
|
||||||
int status;
|
int status;
|
||||||
|
@ -1887,7 +1899,7 @@ int rktio_udp_set_multicast_loopback(rktio_t *rktio, rktio_fd_t *rfd, int on)
|
||||||
|
|
||||||
int rktio_udp_get_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd)
|
int rktio_udp_get_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
u_char ttl;
|
u_char ttl;
|
||||||
rktio_sockopt_len_t ttl_len = sizeof(ttl);
|
rktio_sockopt_len_t ttl_len = sizeof(ttl);
|
||||||
int status;
|
int status;
|
||||||
|
@ -1903,7 +1915,7 @@ int rktio_udp_get_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
|
||||||
int rktio_udp_set_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd, int ttl_val)
|
int rktio_udp_set_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd, int ttl_val)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
u_char ttl = ttl_val;
|
u_char ttl = ttl_val;
|
||||||
rktio_sockopt_len_t ttl_len = sizeof(ttl);
|
rktio_sockopt_len_t ttl_len = sizeof(ttl);
|
||||||
int status;
|
int status;
|
||||||
|
@ -1919,7 +1931,7 @@ int rktio_udp_set_multicast_ttl(rktio_t *rktio, rktio_fd_t *rfd, int ttl_val)
|
||||||
|
|
||||||
char *rktio_udp_multicast_interface(rktio_t *rktio, rktio_fd_t *rfd)
|
char *rktio_udp_multicast_interface(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
struct in_addr intf;
|
struct in_addr intf;
|
||||||
rktio_sockopt_len_t intf_len = sizeof(intf);
|
rktio_sockopt_len_t intf_len = sizeof(intf);
|
||||||
int status;
|
int status;
|
||||||
|
@ -1939,7 +1951,7 @@ char *rktio_udp_multicast_interface(rktio_t *rktio, rktio_fd_t *rfd)
|
||||||
|
|
||||||
int rktio_udp_set_multicast_interface(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *intf_addr)
|
int rktio_udp_set_multicast_interface(rktio_t *rktio, rktio_fd_t *rfd, rktio_addrinfo_t *intf_addr)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
struct in_addr intf;
|
struct in_addr intf;
|
||||||
rktio_sockopt_len_t intf_len = sizeof(intf);
|
rktio_sockopt_len_t intf_len = sizeof(intf);
|
||||||
int status;
|
int status;
|
||||||
|
@ -1964,7 +1976,7 @@ int rktio_udp_change_multicast_group(rktio_t *rktio, rktio_fd_t *rfd,
|
||||||
rktio_addrinfo_t *intf_addr,
|
rktio_addrinfo_t *intf_addr,
|
||||||
int action)
|
int action)
|
||||||
{
|
{
|
||||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||||
struct ip_mreq mreq;
|
struct ip_mreq mreq;
|
||||||
rktio_sockopt_len_t mreq_len = sizeof(mreq);
|
rktio_sockopt_len_t mreq_len = sizeof(mreq);
|
||||||
int status;
|
int status;
|
||||||
|
|
|
@ -26,7 +26,7 @@ static int MyPipe(intptr_t *ph, int flags, rktio_t *rktio)
|
||||||
a[1] = w;
|
a[1] = w;
|
||||||
|
|
||||||
for (near_index = 0; near_index < 2; near_index++) {
|
for (near_index = 0; near_index < 2; near_index++) {
|
||||||
if (flags & (near_index ? RKTIO_NO_INHERIT_INPUT : RKTIO_NO_INHERIT_OUTPUT)) {
|
if (flags & (!near_index ? RKTIO_NO_INHERIT_INPUT : RKTIO_NO_INHERIT_OUTPUT)) {
|
||||||
/* Change the near end to make it non-inheritable, then
|
/* Change the near end to make it non-inheritable, then
|
||||||
close the inheritable one: */
|
close the inheritable one: */
|
||||||
if (!DuplicateHandle(GetCurrentProcess(), a[near_index],
|
if (!DuplicateHandle(GetCurrentProcess(), a[near_index],
|
||||||
|
|
|
@ -94,7 +94,7 @@ void rktio_fdzero(rktio_poll_set_t *fd)
|
||||||
fd->data->skip_sleep = 0;
|
fd->data->skip_sleep = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int find_fd_pos(struct rktio_fd_set_data_t *data, int n)
|
static int find_fd_pos(struct rktio_fd_set_data_t *data, intptr_t n)
|
||||||
{
|
{
|
||||||
intptr_t count = data->count;
|
intptr_t count = data->count;
|
||||||
intptr_t i;
|
intptr_t i;
|
||||||
|
@ -111,7 +111,7 @@ static int find_fd_pos(struct rktio_fd_set_data_t *data, int n)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rktio_fdclr(rktio_poll_set_t *fd, int n)
|
void rktio_fdclr(rktio_poll_set_t *fd, intptr_t n)
|
||||||
{
|
{
|
||||||
struct rktio_fd_set_data_t *data = fd->data;
|
struct rktio_fd_set_data_t *data = fd->data;
|
||||||
intptr_t flag = fd->flags;
|
intptr_t flag = fd->flags;
|
||||||
|
@ -125,7 +125,7 @@ void rktio_fdclr(rktio_poll_set_t *fd, int n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void rktio_fdset(rktio_poll_set_t *fd, int n)
|
void rktio_fdset(rktio_poll_set_t *fd, intptr_t n)
|
||||||
{
|
{
|
||||||
struct rktio_fd_set_data_t *data = fd->data;
|
struct rktio_fd_set_data_t *data = fd->data;
|
||||||
intptr_t flag = fd->flags;
|
intptr_t flag = fd->flags;
|
||||||
|
@ -157,7 +157,7 @@ void rktio_fdset(rktio_poll_set_t *fd, int n)
|
||||||
data->count = count;
|
data->count = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rktio_fdisset(rktio_poll_set_t *fd, int n)
|
int rktio_fdisset(rktio_poll_set_t *fd, intptr_t n)
|
||||||
{
|
{
|
||||||
struct rktio_fd_set_data_t *data = fd->data;
|
struct rktio_fd_set_data_t *data = fd->data;
|
||||||
intptr_t flag = fd->flags;
|
intptr_t flag = fd->flags;
|
||||||
|
@ -469,27 +469,27 @@ void rktio_fdzero(rktio_poll_set_t *fd)
|
||||||
init_fdset_array(fd, 1);
|
init_fdset_array(fd, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rktio_fdclr(rktio_poll_set_t *fd, int n)
|
void rktio_fdclr(rktio_poll_set_t *fd, intptr_t n)
|
||||||
{
|
{
|
||||||
int i;
|
intptr_t i;
|
||||||
for (i = fd->added; i--; ) {
|
for (i = fd->added; i--; ) {
|
||||||
if (fd->sockets[i] == n)
|
if (fd->sockets[i] == n)
|
||||||
fd->sockets[i] = INVALID_SOCKET;
|
fd->sockets[i] = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int next_size(int v) { return (v ? (2 * v) : 10); }
|
static intptr_t next_size(intptr_t v) { return (v ? (2 * v) : 10); }
|
||||||
|
|
||||||
void rktio_fdset(rktio_poll_set_t *fd, int n)
|
void rktio_fdset(rktio_poll_set_t *fd, intptr_t n)
|
||||||
{
|
{
|
||||||
if (fd->added >= fd->last_alloc) {
|
if (fd->added >= fd->last_alloc) {
|
||||||
int na;
|
intptr_t na;
|
||||||
na = next_size(fd->last_alloc);
|
na = next_size(fd->last_alloc);
|
||||||
fd->last_alloc = na;
|
fd->last_alloc = na;
|
||||||
}
|
}
|
||||||
if (fd->added >= fd->alloc) {
|
if (fd->added >= fd->alloc) {
|
||||||
SOCKET *naya;
|
SOCKET *naya;
|
||||||
int na;
|
intptr_t na;
|
||||||
na = next_size(fd->alloc);
|
na = next_size(fd->alloc);
|
||||||
naya = malloc(na * sizeof(SOCKET));
|
naya = malloc(na * sizeof(SOCKET));
|
||||||
memcpy(naya, fd->sockets, fd->alloc * sizeof(SOCKET));
|
memcpy(naya, fd->sockets, fd->alloc * sizeof(SOCKET));
|
||||||
|
@ -498,14 +498,14 @@ void rktio_fdset(rktio_poll_set_t *fd, int n)
|
||||||
fd->alloc = na;
|
fd->alloc = na;
|
||||||
reset_wait_array(fd);
|
reset_wait_array(fd);
|
||||||
}
|
}
|
||||||
fd->sockets[fd->added++] = n;
|
fd->sockets[fd->added++] = (SOCKET)n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rktio_fdisset(rktio_poll_set_t *fd, int n)
|
int rktio_fdisset(rktio_poll_set_t *fd, intptr_t n)
|
||||||
{
|
{
|
||||||
int i;
|
intptr_t i;
|
||||||
for (i = fd->added; i--; ) {
|
for (i = fd->added; i--; ) {
|
||||||
if (fd->sockets[i] == n)
|
if (fd->sockets[i] == (SOCKET)n)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -513,10 +513,10 @@ 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)
|
void rktio_merge_fd_sets(rktio_poll_set_t *fds, rktio_poll_set_t *src_fds)
|
||||||
{
|
{
|
||||||
int i;
|
intptr_t i;
|
||||||
for (i = src_fds->added; i--; ) {
|
for (i = src_fds->added; i--; ) {
|
||||||
if (src_fds->sockets[i] != INVALID_SOCKET)
|
if (src_fds->sockets[i] != INVALID_SOCKET)
|
||||||
rktio_fdset(fds, src_fds->sockets[i]);
|
rktio_fdset(fds, (intptr_t)src_fds->sockets[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +534,8 @@ void rktio_poll_set_add_handle(rktio_t *rktio, intptr_t _h, rktio_poll_set_t *fd
|
||||||
HANDLE h = (HANDLE)_h;
|
HANDLE h = (HANDLE)_h;
|
||||||
rktio_poll_set_t *efd = fds;
|
rktio_poll_set_t *efd = fds;
|
||||||
HANDLE *hs;
|
HANDLE *hs;
|
||||||
int i, new_i, *rps;
|
intptr_t i, new_i;
|
||||||
|
int *rps;
|
||||||
|
|
||||||
if (efd->num_handles == efd->last_alloc_handles) {
|
if (efd->num_handles == efd->last_alloc_handles) {
|
||||||
i = next_size(efd->last_alloc_handles);
|
i = next_size(efd->last_alloc_handles);
|
||||||
|
@ -606,7 +607,7 @@ void rktio_collapse_win_fd(rktio_poll_set_t *fds)
|
||||||
{
|
{
|
||||||
rktio_poll_set_t *rfd, *wfd, *efd;
|
rktio_poll_set_t *rfd, *wfd, *efd;
|
||||||
HANDLE *wa, e;
|
HANDLE *wa, e;
|
||||||
int i, p = 0, mask, j;
|
intptr_t i, p = 0, mask, j;
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
|
|
||||||
rfd = fds;
|
rfd = fds;
|
||||||
|
@ -781,12 +782,12 @@ static int fdset_has_nosleep(rktio_poll_set_t *fds)
|
||||||
|
|
||||||
#ifdef USE_PLAIN_FDS_SET_OPS
|
#ifdef USE_PLAIN_FDS_SET_OPS
|
||||||
|
|
||||||
void rktio_fdclr(rktio_poll_set_t *fd, int n)
|
void rktio_fdclr(rktio_poll_set_t *fd, intptr_t n)
|
||||||
{
|
{
|
||||||
FD_CLR(n, &(fd)->data);
|
FD_CLR(n, &(fd)->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rktio_fdset(rktio_poll_set_t *fd, int n)
|
void rktio_fdset(rktio_poll_set_t *fd, intptr_t n)
|
||||||
{
|
{
|
||||||
# ifdef STORED_ACTUAL_FDSET_LIMIT
|
# ifdef STORED_ACTUAL_FDSET_LIMIT
|
||||||
int mx;
|
int mx;
|
||||||
|
@ -797,7 +798,7 @@ void rktio_fdset(rktio_poll_set_t *fd, int n)
|
||||||
FD_SET(n, &(fd)->data);
|
FD_SET(n, &(fd)->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rktio_fdisset(rktio_poll_set_t *fd, int n)
|
int rktio_fdisset(rktio_poll_set_t *fd, intptr_t n)
|
||||||
{
|
{
|
||||||
return FD_ISSET(n, &(fd)->data);
|
return FD_ISSET(n, &(fd)->data);
|
||||||
}
|
}
|
||||||
|
@ -1207,7 +1208,8 @@ void rktio_sleep(rktio_t *rktio, float nsecs, rktio_poll_set_t *fds, rktio_ltps_
|
||||||
{
|
{
|
||||||
intptr_t result;
|
intptr_t result;
|
||||||
HANDLE *array, just_two_array[2];
|
HANDLE *array, just_two_array[2];
|
||||||
int count, rcount, *rps;
|
intptr_t count, rcount;
|
||||||
|
int *rps;
|
||||||
|
|
||||||
rktio_collapse_win_fd(fds); /* merges */
|
rktio_collapse_win_fd(fds); /* merges */
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
|
|
||||||
struct rktio_t {
|
struct rktio_t {
|
||||||
intptr_t errid;
|
int errid;
|
||||||
int errkind;
|
int errkind;
|
||||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||||
char *last_err_str;
|
char *last_err_str;
|
||||||
|
@ -108,9 +108,9 @@ int rktio_initialize_signal(rktio_t *rktio);
|
||||||
|
|
||||||
rktio_poll_set_t *rktio_get_fdset(rktio_poll_set_t *fdarray, int pos);
|
rktio_poll_set_t *rktio_get_fdset(rktio_poll_set_t *fdarray, int pos);
|
||||||
void rktio_fdzero(rktio_poll_set_t *fd);
|
void rktio_fdzero(rktio_poll_set_t *fd);
|
||||||
void rktio_fdset(rktio_poll_set_t *fd, int n);
|
void rktio_fdset(rktio_poll_set_t *fd, intptr_t n);
|
||||||
void rktio_fdclr(rktio_poll_set_t *fd, int n);
|
void rktio_fdclr(rktio_poll_set_t *fd, intptr_t n);
|
||||||
int rktio_fdisset(rktio_poll_set_t *fd, int n);
|
int rktio_fdisset(rktio_poll_set_t *fd, intptr_t n);
|
||||||
|
|
||||||
# define DECL_FDSET(n, c) rktio_poll_set_t *n
|
# define DECL_FDSET(n, c) rktio_poll_set_t *n
|
||||||
# define INIT_DECL_FDSET(r, w, e) { \
|
# define INIT_DECL_FDSET(r, w, e) { \
|
||||||
|
|
|
@ -1028,12 +1028,13 @@ static char *cmdline_protect(char *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
static intptr_t do_spawnv(rktio_t *rktio,
|
static intptr_t do_spawnv(rktio_t *rktio,
|
||||||
const char *command, const char * const *argv,
|
const char *command, int argc, const char * const *argv,
|
||||||
int exact_cmdline, intptr_t sin, intptr_t sout, intptr_t serr, int *pid,
|
int exact_cmdline, intptr_t sin, intptr_t sout, intptr_t serr, int *pid,
|
||||||
int new_process_group, int chain_termination_here_to_child,
|
int new_process_group, int chain_termination_here_to_child,
|
||||||
void *env, const char *wd)
|
void *env, const char *wd)
|
||||||
{
|
{
|
||||||
int i, l, len = 0, use_jo;
|
intptr_t i, l, len = 0;
|
||||||
|
int use_jo;
|
||||||
intptr_t cr_flag;
|
intptr_t cr_flag;
|
||||||
char *cmdline;
|
char *cmdline;
|
||||||
wchar_t *cmdline_w, *wd_w;
|
wchar_t *cmdline_w, *wd_w;
|
||||||
|
@ -1043,14 +1044,14 @@ static intptr_t do_spawnv(rktio_t *rktio,
|
||||||
if (exact_cmdline) {
|
if (exact_cmdline) {
|
||||||
cmdline = (char *)argv[1];
|
cmdline = (char *)argv[1];
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; argv[i]; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
len += strlen(argv[i]) + 1;
|
len += strlen(argv[i]) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdline = malloc(len);
|
cmdline = malloc(len);
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
for (i = 0; argv[i]; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
l = strlen(argv[i]);
|
l = strlen(argv[i]);
|
||||||
memcpy(cmdline + len, argv[i], l);
|
memcpy(cmdline + len, argv[i], l);
|
||||||
cmdline[len + l] = ' ';
|
cmdline[len + l] = ' ';
|
||||||
|
@ -1205,7 +1206,7 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
|
||||||
int windows_chain_termination_to_child = (flags & RKTIO_PROCESS_WINDOWS_CHAIN_TERMINATION);
|
int windows_chain_termination_to_child = (flags & RKTIO_PROCESS_WINDOWS_CHAIN_TERMINATION);
|
||||||
int i;
|
int i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* avoid compiler warnings: */
|
/* avoid compiler warnings: */
|
||||||
to_subprocess[0] = -1;
|
to_subprocess[0] = -1;
|
||||||
to_subprocess[1] = -1;
|
to_subprocess[1] = -1;
|
||||||
|
@ -1228,8 +1229,8 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
|
||||||
if (stdin_fd) {
|
if (stdin_fd) {
|
||||||
to_subprocess[0] = rktio_fd_system_fd(rktio, stdin_fd);
|
to_subprocess[0] = rktio_fd_system_fd(rktio, stdin_fd);
|
||||||
RKTIO_COPY_FOR_SUBPROCESS(to_subprocess, 0);
|
RKTIO_COPY_FOR_SUBPROCESS(to_subprocess, 0);
|
||||||
} else if (rktio_make_os_pipe(rktio, to_subprocess, 1)) {
|
} else if (rktio_make_os_pipe(rktio, to_subprocess, RKTIO_NO_INHERIT_OUTPUT)) {
|
||||||
if (stdout_fd) { RKTIO_CLOSE_SUBPROCESS_COPY(from_subprocess, RKTIO_NO_INHERIT_OUTPUT); }
|
if (stdout_fd) { RKTIO_CLOSE_SUBPROCESS_COPY(from_subprocess, 1); }
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1276,7 +1277,7 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
|
||||||
pid = 0;
|
pid = 0;
|
||||||
|
|
||||||
spawn_status = do_spawnv(rktio,
|
spawn_status = do_spawnv(rktio,
|
||||||
command, (const char * const *)argv,
|
command, argc, (const char * const *)argv,
|
||||||
windows_exact_cmdline,
|
windows_exact_cmdline,
|
||||||
to_subprocess[0],
|
to_subprocess[0],
|
||||||
from_subprocess[1],
|
from_subprocess[1],
|
||||||
|
|
2
racket/src/worksp/.gitignore
vendored
2
racket/src/worksp/.gitignore
vendored
|
@ -13,6 +13,8 @@
|
||||||
*/*.suo
|
*/*.suo
|
||||||
*/*.sdf
|
*/*.sdf
|
||||||
*/*.sln.cache
|
*/*.sln.cache
|
||||||
|
*/*.db
|
||||||
|
*/.vs
|
||||||
|
|
||||||
# potentially generated by "genvsx"
|
# potentially generated by "genvsx"
|
||||||
*/*X.vcxproj
|
*/*X.vcxproj
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
<Configurations>
|
<Configurations>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Debug|Win32"
|
Name="Debug|Win32"
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)\..\libffi\$(ConfigurationName)"
|
||||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
IntermediateDirectory="..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||||
ConfigurationType="4"
|
ConfigurationType="4"
|
||||||
CharacterSet="1"
|
CharacterSet="1"
|
||||||
>
|
>
|
||||||
|
@ -41,8 +41,8 @@
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)\..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
IntermediateDirectory="..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||||
ConfigurationType="4"
|
ConfigurationType="4"
|
||||||
CharacterSet="1"
|
CharacterSet="1"
|
||||||
>
|
>
|
||||||
|
@ -61,8 +61,8 @@
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Release|Win32"
|
Name="Release|Win32"
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)\..\libffi\$(ConfigurationName)"
|
||||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
IntermediateDirectory="..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||||
ConfigurationType="4"
|
ConfigurationType="4"
|
||||||
CharacterSet="1"
|
CharacterSet="1"
|
||||||
WholeProgramOptimization="1"
|
WholeProgramOptimization="1"
|
||||||
|
@ -82,8 +82,8 @@
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)\..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
IntermediateDirectory="..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||||
ConfigurationType="4"
|
ConfigurationType="4"
|
||||||
CharacterSet="1"
|
CharacterSet="1"
|
||||||
WholeProgramOptimization="1"
|
WholeProgramOptimization="1"
|
||||||
|
|
|
@ -65,8 +65,8 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||||
<TargetName>libffi</TargetName>
|
<TargetName>libffi</TargetName>
|
||||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)\..\libffi\$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
<IntDir>..\libffi\$(Platform)\$(Configuration)\</IntDir>
|
||||||
<PlatformToolset>v100</PlatformToolset>
|
<PlatformToolset>v100</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
<Configurations>
|
<Configurations>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Debug|Win32"
|
Name="Debug|Win32"
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)\..\librktio\$(ConfigurationName)"
|
||||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
IntermediateDirectory="..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||||
ConfigurationType="4"
|
ConfigurationType="4"
|
||||||
CharacterSet="1"
|
CharacterSet="1"
|
||||||
>
|
>
|
||||||
|
@ -41,8 +41,8 @@
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)\..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
IntermediateDirectory="..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||||
ConfigurationType="4"
|
ConfigurationType="4"
|
||||||
CharacterSet="1"
|
CharacterSet="1"
|
||||||
>
|
>
|
||||||
|
@ -61,8 +61,8 @@
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Release|Win32"
|
Name="Release|Win32"
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)\..\librktio\$(ConfigurationName)"
|
||||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
IntermediateDirectory="..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||||
ConfigurationType="4"
|
ConfigurationType="4"
|
||||||
CharacterSet="1"
|
CharacterSet="1"
|
||||||
WholeProgramOptimization="1"
|
WholeProgramOptimization="1"
|
||||||
|
@ -82,8 +82,8 @@
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
<Configuration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)\..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
IntermediateDirectory="..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||||
ConfigurationType="4"
|
ConfigurationType="4"
|
||||||
CharacterSet="1"
|
CharacterSet="1"
|
||||||
WholeProgramOptimization="1"
|
WholeProgramOptimization="1"
|
||||||
|
|
|
@ -65,8 +65,8 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||||
<TargetName>librktio</TargetName>
|
<TargetName>librktio</TargetName>
|
||||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)\..\librktio\$(Platform)\$(Configuration)\</OutDir>
|
||||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
<IntDir>..\librktio\$(Platform)\$(Configuration)\</IntDir>
|
||||||
<PlatformToolset>v100</PlatformToolset>
|
<PlatformToolset>v100</PlatformToolset>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
|
|
|
@ -2,5 +2,8 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
typedef _int64 rktio_int64_t;
|
||||||
|
typedef unsigned _int64 rktio_uint64_t;
|
||||||
|
|
||||||
/* whether getaddrinfo works */
|
/* whether getaddrinfo works */
|
||||||
#define HAVE_GETADDRINFO 1
|
#define HAVE_GETADDRINFO 1
|
||||||
|
|
Loading…
Reference in New Issue
Block a user