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
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#ifndef DOS_FILE_SYSTEM
|
||||
# include <sys/time.h>
|
||||
#endif
|
||||
#ifndef NO_USER_BREAK_HANDLER
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
|
|
@ -200,8 +200,6 @@ static int do_main_stack_setup(int no_auto_statics, Scheme_Nested_Main _main, vo
|
|||
#endif
|
||||
|
||||
scheme_set_stack_base(PROMPT_STACK(stack_start), no_auto_statics);
|
||||
|
||||
scheme_rktio = rktio_init();
|
||||
|
||||
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_init_os_thread();
|
||||
scheme_rktio = rktio_init();
|
||||
#ifdef MZ_USE_MZRT
|
||||
scheme_init_glib_log_queue();
|
||||
#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)
|
||||
{
|
||||
rktio_poll_set_t *ps;
|
||||
ps = rktio_make_poll_set(rktio);
|
||||
check_valid(ps);
|
||||
rktio_poll_add(rktio, fd, ps, RKTIO_POLL_READ);
|
||||
rktio_sleep(rktio, 0, ps, NULL);
|
||||
rktio_poll_set_forget(rktio, ps);
|
||||
while (rktio_poll_read_ready(rktio, fd) == RKTIO_POLL_NOT_READY) {
|
||||
rktio_poll_set_t *ps;
|
||||
ps = rktio_make_poll_set(rktio);
|
||||
check_valid(ps);
|
||||
rktio_poll_add(rktio, fd, ps, RKTIO_POLL_READ);
|
||||
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)
|
||||
{
|
||||
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: */
|
||||
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
|
||||
amt = rktio_write(rktio, fd2, "hello", 5);
|
||||
amt = rktio_write(rktio, fd2, "hola\n", 5);
|
||||
check_valid(amt == 5);
|
||||
|
||||
|
||||
if (!immediate_available) {
|
||||
/* Wait for read to be ready; should not block for long */
|
||||
wait_read(rktio, fd);
|
||||
}
|
||||
|
||||
|
||||
check_valid(rktio_poll_read_ready(rktio, fd) == RKTIO_POLL_READY);
|
||||
if (lt) {
|
||||
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
|
||||
amt = rktio_read(rktio, fd, buffer, sizeof(buffer));
|
||||
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));
|
||||
|
||||
/* 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_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;
|
||||
|
||||
int r;
|
||||
|
||||
if (!limit)
|
||||
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);
|
||||
if (!amt)
|
||||
break;
|
||||
if (amt == RKTIO_WRITE_ERROR)
|
||||
break;
|
||||
}
|
||||
check_valid(i > 0);
|
||||
if (!rktio_fd_is_udp(rktio, fd2))
|
||||
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;
|
||||
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 < limit);
|
||||
if (verbose)
|
||||
printf(" read empty after %ld\n", (long)i);
|
||||
}
|
||||
|
||||
void check_many_lookup(rktio_t *rktio)
|
||||
|
@ -329,7 +372,7 @@ void check_many_lookup(rktio_t *rktio)
|
|||
check_valid(lookup[i]);
|
||||
}
|
||||
|
||||
for (j = 0; j < LOOKUPS_N; j++) {
|
||||
for (j = 0; j < LOOKUPS_N; ) {
|
||||
ps = rktio_make_poll_set(rktio);
|
||||
check_valid(ps);
|
||||
|
||||
|
@ -343,6 +386,7 @@ void check_many_lookup(rktio_t *rktio)
|
|||
|
||||
for (i = 0; i < LOOKUPS_N; i++) {
|
||||
if (lookup[i] && (rktio_poll_addrinfo_lookup_ready(rktio, lookup[i]) == RKTIO_POLL_READY)) {
|
||||
j++;
|
||||
if ((i % 3) == 2)
|
||||
rktio_addrinfo_lookup_stop(rktio, lookup[i]);
|
||||
else {
|
||||
|
@ -351,7 +395,6 @@ void check_many_lookup(rktio_t *rktio)
|
|||
rktio_addrinfo_free(rktio, addr);
|
||||
}
|
||||
lookup[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -363,17 +406,20 @@ rktio_addrinfo_t *lookup_loop(rktio_t *rktio,
|
|||
{
|
||||
rktio_addrinfo_lookup_t *lookup;
|
||||
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);
|
||||
check_valid(lookup);
|
||||
|
||||
rktio_poll_add_addrinfo_lookup(rktio, lookup, ps);
|
||||
rktio_sleep(rktio, 0, ps, NULL);
|
||||
rktio_poll_set_forget(rktio, ps);
|
||||
while (rktio_poll_addrinfo_lookup_ready(rktio, lookup) == RKTIO_POLL_NOT_READY) {
|
||||
rktio_poll_set_t *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);
|
||||
|
||||
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_poll_set_t *ps;
|
||||
rktio_fd_t *fd;
|
||||
rktio_fd_t *fd = NULL;
|
||||
|
||||
conn = rktio_start_connect(rktio, addr, local_addr);
|
||||
check_valid(conn);
|
||||
|
||||
while (1) {
|
||||
while (!fd) {
|
||||
ps = rktio_make_poll_set(rktio);
|
||||
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)) {
|
||||
/* loop to try again */
|
||||
} else {
|
||||
/* report other error: */
|
||||
check_valid(fd);
|
||||
}
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
@ -541,9 +587,17 @@ int main(int argc, char **argv)
|
|||
check_valid(perms != -1);
|
||||
check_valid(perms & (RKTIO_PERMISSION_READ << 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));
|
||||
rktio_set_file_or_directory_permissions(rktio, "test1", perms);
|
||||
{
|
||||
int ok;
|
||||
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);
|
||||
check_valid(cp);
|
||||
|
@ -638,7 +692,7 @@ int main(int argc, char **argv)
|
|||
|
||||
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: */
|
||||
pipe_fds = rktio_make_pipe(rktio, 0);
|
||||
|
@ -647,9 +701,12 @@ int main(int argc, char **argv)
|
|||
fd2 = pipe_fds[1];
|
||||
free(pipe_fds);
|
||||
|
||||
check_fill_write(rktio, fd2, NULL, 0);
|
||||
check_drain_read(rktio, fd, 0);
|
||||
|
||||
check_fill_write(rktio, fd2, NULL, 0, verbose);
|
||||
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, fd2));
|
||||
}
|
||||
|
@ -664,7 +721,7 @@ int main(int argc, char **argv)
|
|||
rktio_listener_t *lnr;
|
||||
|
||||
check_many_lookup(rktio);
|
||||
|
||||
|
||||
addr = lookup_loop(rktio, NULL, 4536, -1, 1, 1);
|
||||
|
||||
lnr = rktio_listen(rktio, addr, 5, 1);
|
||||
|
@ -722,8 +779,10 @@ int main(int argc, char **argv)
|
|||
|
||||
fd2 = rktio_accept(rktio, lnr);
|
||||
|
||||
check_fill_write(rktio, fd2, NULL, 0);
|
||||
check_drain_read(rktio, fd, 0);
|
||||
printf(" fill\n");
|
||||
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, fd2));
|
||||
|
@ -774,8 +833,8 @@ int main(int argc, char **argv)
|
|||
addr = lookup_loop(rktio, "localhost", 4536, -1, 0, 0);
|
||||
check_valid(addr);
|
||||
|
||||
check_fill_write(rktio, fd2, addr, AMOUNT_FOR_UDP);
|
||||
check_drain_read(rktio, fd, AMOUNT_FOR_UDP+1);
|
||||
check_fill_write(rktio, fd2, addr, AMOUNT_FOR_UDP, verbose);
|
||||
check_drain_read(rktio, fd, AMOUNT_FOR_UDP+1, verbose);
|
||||
|
||||
rktio_addrinfo_free(rktio, addr);
|
||||
rktio_addrinfo_free(rktio, intf_addr);
|
||||
|
@ -792,12 +851,18 @@ int main(int argc, char **argv)
|
|||
{
|
||||
rktio_status_t *status;
|
||||
rktio_process_result_t *result;
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
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_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;
|
||||
|
||||
result = rktio_process(rktio, argv[0], 1, argv,
|
||||
|
||||
result = rktio_process(rktio, argv[0], argc, argv,
|
||||
NULL, NULL, err_fd,
|
||||
pwd, envvars,
|
||||
0);
|
||||
|
@ -826,8 +891,14 @@ int main(int argc, char **argv)
|
|||
rktio_process_forget(rktio, result->process);
|
||||
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` */
|
||||
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,
|
||||
NULL, NULL, err_fd,
|
||||
pwd, envvars,
|
||||
|
@ -852,7 +923,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
pause_for_process(rktio, result->process, dont_rely_on_sigchild);
|
||||
|
||||
|
||||
status = rktio_process_status(rktio, result->process);
|
||||
check_valid(status);
|
||||
check_valid(!status->running);
|
||||
|
@ -862,8 +933,9 @@ int main(int argc, char **argv)
|
|||
{
|
||||
char buffer[1];
|
||||
intptr_t amt;
|
||||
wait_read(rktio, result->stdout_fd);
|
||||
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));
|
||||
|
@ -874,8 +946,18 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
{
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
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)
|
||||
printf(" envvars\n");
|
||||
|
||||
|
@ -886,10 +968,10 @@ int main(int argc, char **argv)
|
|||
check_valid(!strcmp(s, "howdy"));
|
||||
free(s);
|
||||
|
||||
result = rktio_process(rktio, argv[0], 2, argv,
|
||||
result = rktio_process(rktio, argv[0], argc, argv,
|
||||
NULL, NULL, err_fd,
|
||||
pwd, envvars,
|
||||
0);
|
||||
flags);
|
||||
check_valid(result);
|
||||
|
||||
/* Assume that a pipe can buffer the minimal output from `printenv`: */
|
||||
|
@ -900,8 +982,13 @@ int main(int argc, char **argv)
|
|||
char buffer[32];
|
||||
intptr_t amt;
|
||||
amt = rktio_read(rktio, result->stdout_fd, buffer, sizeof(buffer));
|
||||
check_valid(amt == 6);
|
||||
check_valid(!strncmp(buffer, "howdy\n", 6));
|
||||
if (expect_crlf) {
|
||||
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));
|
||||
|
@ -919,7 +1006,11 @@ int main(int argc, char **argv)
|
|||
/* Filesystem-change events */
|
||||
|
||||
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_poll_set_t *ps;
|
||||
rktio_ltps_t *lt;
|
||||
|
@ -956,7 +1047,19 @@ int main(int argc, char **argv)
|
|||
amt = rktio_write(rktio, fd2, "hola", 4);
|
||||
check_valid(amt == 4);
|
||||
|
||||
printf("wait...\n");
|
||||
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);
|
||||
|
||||
|
@ -967,6 +1070,8 @@ int main(int argc, char **argv)
|
|||
|
||||
if (lt)
|
||||
rktio_ltps_close(rktio, lt);
|
||||
|
||||
free(path);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
|
@ -1061,7 +1166,7 @@ int main(int argc, char **argv)
|
|||
today->zone_offset, today->zone_offset / (60 * 60),
|
||||
(today->is_dst ? ";DST" : ""),
|
||||
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);
|
||||
|
||||
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);
|
||||
/* Can report `RKTIO_ERROR_EXISTS` in place of system error,
|
||||
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);
|
||||
/* 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
|
||||
error. Although rktio_write() is intended to write only bytes that
|
||||
can be fully delivered to the OS, there may be OS limitations that
|
||||
require buffering (e.g., on Windows). Use
|
||||
rktio_poll_write_flushed() to make sure it's completely flushed
|
||||
before closing. */
|
||||
require buffering (e.g., on Windows). Use `rktio_poll_write_flushed`
|
||||
to make sure the data is received by the destination before closing
|
||||
`fd`. */
|
||||
|
||||
#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)
|
||||
|
||||
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_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);
|
||||
/* Waits up to `nsecs` seconds (or forever if `nsecs` is 0) or until
|
||||
something registered with `fds` or `lt` is ready. */
|
||||
/* Waits up to `nsecs` seconds (or forever if `nsecs` is 0), until
|
||||
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 */
|
||||
|
|
|
@ -32,7 +32,7 @@ char **rktio_get_environ_array(void)
|
|||
|
||||
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
|
||||
if (!s[0]) return 0;
|
||||
#endif
|
||||
|
@ -159,8 +159,7 @@ rktio_envvars_t *rktio_envvars(rktio_t *rktio)
|
|||
i = 0;
|
||||
while (e[i]) {
|
||||
count++;
|
||||
for (i = 0; e[i]; ) {
|
||||
}
|
||||
while (e[i]) i++;
|
||||
i++;
|
||||
}
|
||||
|
||||
|
@ -171,7 +170,8 @@ rktio_envvars_t *rktio_envvars(rktio_t *rktio)
|
|||
envvars->vals = malloc(count * sizeof(char *));
|
||||
|
||||
count = 0;
|
||||
for (i = 0; e[i]; ) {
|
||||
i = 0;
|
||||
while (e[i]) {
|
||||
start = i;
|
||||
while (e[i]) { i++; }
|
||||
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);
|
||||
free(p);
|
||||
i++;
|
||||
count++;
|
||||
}
|
||||
|
||||
FreeEnvironmentStringsW(e);
|
||||
|
@ -382,7 +383,7 @@ void *rktio_envvars_to_block(rktio_t *rktio, rktio_envvars_t *envvars)
|
|||
intptr_t len = 0, slen;
|
||||
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->vals[i]));
|
||||
len += 2;
|
||||
|
|
|
@ -115,7 +115,7 @@ const char *rktio_get_error_string(rktio_t *rktio, int kind, int errid)
|
|||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
else if (kind == RKTIO_ERROR_KIND_WINDOWS) {
|
||||
wchar_t mbuf[256];
|
||||
int len, i;
|
||||
intptr_t len, i;
|
||||
if ((len = FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_IGNORE_INSERTS),
|
||||
NULL,
|
||||
|
@ -128,7 +128,7 @@ const char *rktio_get_error_string(rktio_t *rktio, int kind, int errid)
|
|||
mbuf[len] = 0;
|
||||
es = NARROW_PATH_copy(mbuf);
|
||||
/* Remove newlines: */
|
||||
for (i = strlen(s) - 1; i > 0; i--) {
|
||||
for (i = strlen(es) - 1; i > 0; i--) {
|
||||
if (isspace(es[i]))
|
||||
es[i] = 0;
|
||||
else
|
||||
|
|
|
@ -34,7 +34,7 @@ struct rktio_fd_t {
|
|||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
union {
|
||||
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_Output_Thread *oth; /* output mode */
|
||||
|
@ -53,11 +53,11 @@ struct rktio_fd_t {
|
|||
typedef struct Win_FD_Input_Thread {
|
||||
/* This is malloced for use in a Win32 thread */
|
||||
HANDLE fd;
|
||||
volatile int avail, err, checking;
|
||||
int avail, offset, err, checking, you_clean_up;
|
||||
int *refcount;
|
||||
HANDLE eof;
|
||||
unsigned char *buffer;
|
||||
HANDLE checking_sema, ready_sema, you_clean_up_sema;
|
||||
HANDLE lock_sema, checking_sema, ready_sema;
|
||||
HANDLE 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
|
||||
write has ben flushed, which in turn is needed to
|
||||
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
|
||||
to the main thread. For efficiency, we request
|
||||
flush checking only when needed (instead of
|
||||
after every write); needflush indicates that
|
||||
a flush check is currently needed, but hasn't
|
||||
been started. */
|
||||
volatile int done, err_no;
|
||||
volatile unsigned int buflen, bufstart, bufend; /* used for blocking, only */
|
||||
int done, err_no, you_clean_up;
|
||||
unsigned int buflen, bufstart, bufend; /* used for blocking, only */
|
||||
unsigned char *buffer; /* used for blocking, only */
|
||||
int *refcount;
|
||||
HANDLE lock_sema, work_sema, ready_sema, you_clean_up_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 lock_sema, work_sema, ready_sema;
|
||||
HANDLE thread;
|
||||
} Win_FD_Output_Thread;
|
||||
|
||||
# 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 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 void WindowsFDOCleanup(Win_FD_Output_Thread *oth);
|
||||
static void WindowsFDOCleanup(Win_FD_Output_Thread *oth, int close_mode);
|
||||
|
||||
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 */
|
||||
/*========================================================================*/
|
||||
|
||||
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 *rfd;
|
||||
|
@ -200,7 +155,7 @@ rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes)
|
|||
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (modes & RKTIO_OPEN_SOCKET)
|
||||
rfd->sock = system_fd;
|
||||
rfd->sock = (SOCKET)system_fd;
|
||||
else
|
||||
rfd->fd = (HANDLE)system_fd;
|
||||
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
|
||||
|
||||
if (modes & RKTIO_OPEN_READ)
|
||||
init_read_fd(rktio, rfd);
|
||||
|
||||
if ((modes & RKTIO_OPEN_SOCKET) && (modes & RKTIO_OPEN_INIT))
|
||||
rktio_socket_init(rktio, rfd);
|
||||
|
||||
|
@ -236,7 +188,7 @@ intptr_t rktio_fd_system_fd(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||
return rfd->sock;
|
||||
return (intptr_t)rfd->sock;
|
||||
else
|
||||
return (intptr_t)rfd->fd;
|
||||
#endif
|
||||
|
@ -262,7 +214,9 @@ rktio_fd_t *rktio_std_fd(rktio_t *rktio, int which)
|
|||
which = STD_ERROR_HANDLE;
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -400,53 +354,8 @@ static rktio_ok_t do_close(rktio_t *rktio, rktio_fd_t *rfd, int set_error)
|
|||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||
return rktio_socket_close(rktio, rfd, set_error);
|
||||
|
||||
if (rfd->th) {
|
||||
CSI_proc csi;
|
||||
|
||||
/* -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 (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 */
|
||||
}
|
||||
deinit_fd(rktio, rfd, 1);
|
||||
|
||||
ok = 1;
|
||||
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)
|
||||
{
|
||||
#ifdef RKTIO_WINDOWS_SYSTEM
|
||||
deinit_fd(rktio, rfd, 1);
|
||||
#endif
|
||||
free(rfd);
|
||||
}
|
||||
|
||||
|
@ -572,7 +484,9 @@ int rktio_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||
return rktio_socket_poll_read_ready(rktio, rfd);
|
||||
|
||||
|
||||
init_read_fd(rktio, rfd);
|
||||
|
||||
if (!rfd->th) {
|
||||
/* No thread -- so wait works. This case isn't actually used
|
||||
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;
|
||||
} else {
|
||||
/* Has the reader thread pulled in data? */
|
||||
WaitForSingleObject(rfd->th->lock_sema, INFINITE);
|
||||
if (rfd->th->checking) {
|
||||
/* The thread is still trying, last we knew. Check the
|
||||
data-is-ready sema: */
|
||||
if (WaitForSingleObject(rfd->th->ready_sema, 0) == WAIT_OBJECT_0) {
|
||||
rfd->th->checking = 0;
|
||||
return RKTIO_POLL_READY;
|
||||
}
|
||||
} else if (rfd->th->avail || rfd->th->err || rfd->th->eof)
|
||||
/* The thread is still trying.
|
||||
Clean up any signals that we may have ignored before. */
|
||||
WaitForSingleObject(rfd->th->ready_sema, 0);
|
||||
} else if (rfd->th->avail || rfd->th->err || rfd->th->eof) {
|
||||
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||
return RKTIO_POLL_READY; /* other thread found data */
|
||||
else {
|
||||
} else {
|
||||
/* Doesn't have anything, and it's not even looking. Tell it
|
||||
to look: */
|
||||
rfd->th->checking = 1;
|
||||
ReleaseSemaphore(rfd->th->checking_sema, 1, NULL);
|
||||
}
|
||||
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -647,11 +561,14 @@ int poll_write_ready_or_flushed(rktio_t *rktio, rktio_fd_t *rfd, int check_flush
|
|||
}
|
||||
#endif
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||
if (rfd->modes & RKTIO_OPEN_SOCKET) {
|
||||
if (check_flushed)
|
||||
return RKTIO_POLL_READY;
|
||||
return rktio_socket_poll_write_ready(rktio, rfd);
|
||||
}
|
||||
|
||||
if (rfd->oth) {
|
||||
/* Pipe output that can block... */
|
||||
/* Pipe output that can block or needs a background flush */
|
||||
int retval;
|
||||
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;
|
||||
} else
|
||||
retval = oth->flushed;
|
||||
} else
|
||||
retval = (oth->err_no || (check_flushed
|
||||
? !oth->buflen
|
||||
: (oth->buflen < RKTIO_FD_BUFFSIZE)));
|
||||
if (!retval && !check_flushed)
|
||||
WaitForSingleObject(oth->ready_sema, 0); /* clear any leftover state */
|
||||
if (!retval) {
|
||||
/* While we hold the lock, clear any leftover notifications */
|
||||
WaitForSingleObject(oth->ready_sema, 0);
|
||||
}
|
||||
} else {
|
||||
/* 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);
|
||||
|
||||
return retval;
|
||||
return (retval ? RKTIO_POLL_READY : 0);
|
||||
} else
|
||||
return RKTIO_POLL_READY; /* non-blocking output, such as a console, or haven't written yet */
|
||||
#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;
|
||||
|
||||
if (modes & RKTIO_POLL_READ) {
|
||||
RKTIO_FD_SET(rfd->sock, fds);
|
||||
RKTIO_FD_SET((intptr_t)rfd->sock, fds);
|
||||
}
|
||||
if (modes & RKTIO_POLL_WRITE) {
|
||||
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);
|
||||
RKTIO_FD_SET(rfd->sock, fds2);
|
||||
RKTIO_FD_SET((intptr_t)rfd->sock, fds2);
|
||||
} else {
|
||||
if (modes & RKTIO_POLL_READ) {
|
||||
init_read_fd(rktio, rfd);
|
||||
if (rfd->th) {
|
||||
/* See fd_byte_ready */
|
||||
WaitForSingleObject(rfd->th->lock_sema, INFINITE);
|
||||
if (!rfd->th->checking) {
|
||||
if (rfd->th->avail || rfd->th->err || rfd->th->eof) {
|
||||
/* Data is ready. We shouldn't be trying to sleep, so force an
|
||||
immediate wake-up: */
|
||||
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||
rktio_poll_set_add_nosleep(rktio, fds);
|
||||
} else {
|
||||
/* Ask the reader thread to start checking for data */
|
||||
rfd->th->checking = 1;
|
||||
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);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||
rktio_poll_set_add_handle(rktio, (intptr_t)rfd->th->ready_sema, fds, 1);
|
||||
}
|
||||
} else if (rktio_fd_is_regular_file(rktio, rfd)) {
|
||||
/* regular files never block */
|
||||
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
|
||||
if (rfd->modes & RKTIO_OPEN_SOCKET)
|
||||
return rktio_socket_read(rktio, rfd, buffer, len);
|
||||
|
||||
|
||||
init_read_fd(rktio, rfd);
|
||||
|
||||
if (!rfd->th) {
|
||||
/* We can read directly. This must be a regular file, where
|
||||
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))
|
||||
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. */
|
||||
WaitForSingleObject(rfd->th->lock_sema, INFINITE);
|
||||
if (rfd->th->eof) {
|
||||
if (rfd->th->eof != INVALID_HANDLE_VALUE) {
|
||||
ReleaseSemaphore(rfd->th->eof, 1, NULL);
|
||||
rfd->th->eof = NULL;
|
||||
}
|
||||
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||
return RKTIO_READ_EOF;
|
||||
} else if (rfd->th->err) {
|
||||
ReleaseSemaphore(rfd->th->lock_sema, 1, NULL);
|
||||
set_windows_error(rfd->th->err);
|
||||
return RKTIO_READ_ERROR;
|
||||
} else {
|
||||
intptr_t bc = rfd->th->avail;
|
||||
rfd->th->avail = 0;
|
||||
memcpy(buffer, rfd->buffer, bc);
|
||||
if (bc > len)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -923,6 +869,88 @@ static intptr_t rktio_adjust_input_text(rktio_fd_t *rfd, char *buffer, char *is_
|
|||
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)
|
||||
{
|
||||
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: */
|
||||
WaitForSingleObject(th->checking_sema, INFINITE);
|
||||
|
||||
WaitForSingleObject(th->lock_sema, INFINITE);
|
||||
if (th->checking < 0)
|
||||
break;
|
||||
|
||||
if (ReadFile(th->fd, th->buffer, toget, &got, NULL)) {
|
||||
th->avail = got;
|
||||
if (!got) {
|
||||
/* We interpret a send of 0 bytes as a mid-stream EOF. */
|
||||
eof_wait = CreateSemaphore(NULL, 0, 1, NULL);
|
||||
th->eof = eof_wait;
|
||||
}
|
||||
if (th->avail) {
|
||||
/* Spurious wake-up? */
|
||||
ReleaseSemaphore(th->lock_sema, 1, NULL);
|
||||
} else {
|
||||
int err;
|
||||
err = GetLastError();
|
||||
if (err == ERROR_BROKEN_PIPE) {
|
||||
th->eof = INVALID_HANDLE_VALUE;
|
||||
perma_eof = 1;
|
||||
} else
|
||||
th->err = err;
|
||||
}
|
||||
ReleaseSemaphore(th->lock_sema, 1, NULL);
|
||||
if (ReadFile(th->fd, th->buffer, toget, &got, NULL)) {
|
||||
WaitForSingleObject(th->lock_sema, INFINITE);
|
||||
th->avail = got;
|
||||
th->offset = 0;
|
||||
if (!got) {
|
||||
/* 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: */
|
||||
ReleaseSemaphore(th->ready_sema, 1, NULL);
|
||||
th->checking = 0;
|
||||
|
||||
if (eof_wait) {
|
||||
WaitForSingleObject(eof_wait, INFINITE);
|
||||
eof_wait = NULL;
|
||||
/* Notify main program that we found something: */
|
||||
ReleaseSemaphore(th->ready_sema, 1, 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: */
|
||||
if (WaitForSingleObject(th->you_clean_up_sema, 0) != WAIT_OBJECT_0) {
|
||||
WindowsFDICleanup(th);
|
||||
} /* otherwise, main program is responsible for clean-up */
|
||||
if (th->you_clean_up) {
|
||||
WindowsFDICleanup(th, th->you_clean_up);
|
||||
} else {
|
||||
/* otherwise, main program is responsible for clean-up */
|
||||
th->you_clean_up = 1;
|
||||
ReleaseSemaphore(th->lock_sema, 1, NULL);
|
||||
}
|
||||
|
||||
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->ready_sema);
|
||||
CloseHandle(th->you_clean_up_sema);
|
||||
|
||||
CloseHandle(th->fd);
|
||||
if (close_mode != -1)
|
||||
CloseHandle(th->fd);
|
||||
|
||||
free(th->buffer);
|
||||
free(th);
|
||||
|
@ -1097,7 +1150,7 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
|||
flushed). */
|
||||
intptr_t out_len = 0;
|
||||
int ok, errsaved;
|
||||
|
||||
|
||||
if (!rfd->oth || rfd->oth->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));
|
||||
} else
|
||||
nonblocking = 1; /* must be, or we would not have gotten here */
|
||||
|
||||
|
||||
if (nonblocking) {
|
||||
/* Unless we're still trying to flush old data, write to the
|
||||
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))) {
|
||||
towrite = towrite >> 1;
|
||||
if (!towrite) {
|
||||
get_windows_error();
|
||||
return RKTIO_WRITE_ERROR;
|
||||
/* leave ok as 1 and winwrote as 0 */
|
||||
break;
|
||||
}
|
||||
} else
|
||||
break;
|
||||
|
@ -1177,32 +1230,42 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
|||
|
||||
if (ok)
|
||||
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... */
|
||||
|
||||
if (!rfd->oth) {
|
||||
if (ok && (out_len > 0) && !rfd->oth) {
|
||||
/* We create a thread even for pipes that can be put in
|
||||
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;
|
||||
HANDLE h;
|
||||
DWORD id;
|
||||
unsigned char *bfr;
|
||||
HANDLE sm;
|
||||
|
||||
oth = malloc(sizeof(Win_FD_Output_Thread));
|
||||
oth = calloc(1, sizeof(Win_FD_Output_Thread));
|
||||
rfd->oth = oth;
|
||||
|
||||
oth->nonblocking = nonblocking;
|
||||
|
||||
if (!nonblocking) {
|
||||
/* Create the buffer to communicate with the writing thread. */
|
||||
bfr = malloc(RKTIO_FD_BUFFSIZE);
|
||||
oth->buffer = bfr;
|
||||
oth->flushed = 0;
|
||||
oth->needflush = 0;
|
||||
} else {
|
||||
/* No buffer needed */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1219,9 +1282,7 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
|||
oth->work_sema = sm;
|
||||
sm = CreateSemaphore(NULL, 1, 1, NULL);
|
||||
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);
|
||||
|
||||
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
|
||||
done... */
|
||||
|
||||
if (!rfd->oth->nonblocking) {
|
||||
if (rfd->oth && !rfd->oth->nonblocking) {
|
||||
/* This case is for Win 95/98/Me anonymous pipes and
|
||||
character devices. We haven't written anything yet! We
|
||||
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
|
||||
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;
|
||||
|
||||
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;
|
||||
ok = 0;
|
||||
} 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;
|
||||
} else {
|
||||
intptr_t topp;
|
||||
|
@ -1305,13 +1370,6 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr
|
|||
ok = 1;
|
||||
}
|
||||
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)
|
||||
|
@ -1373,23 +1431,54 @@ static intptr_t rktio_recount_output_text(const char *orig_buffer, const char *b
|
|||
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)
|
||||
{
|
||||
DWORD towrite, wrote, start;
|
||||
int ok, more_work = 0, err_no;
|
||||
|
||||
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) {
|
||||
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
||||
WaitForSingleObject(oth->work_sema, INFINITE);
|
||||
|
||||
FlushFileBuffers(oth->fd);
|
||||
|
||||
|
||||
WaitForSingleObject(oth->lock_sema, INFINITE);
|
||||
oth->flushed = 1;
|
||||
ReleaseSemaphore(oth->ready_sema, 1, NULL);
|
||||
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
||||
}
|
||||
/* lock held on loop exit */
|
||||
} else {
|
||||
/* Blocking mode. We do the writing work. This case is for
|
||||
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)
|
||||
WaitForSingleObject(oth->work_sema, INFINITE);
|
||||
|
||||
WaitForSingleObject(oth->lock_sema, INFINITE);
|
||||
if (oth->done)
|
||||
break;
|
||||
|
||||
WaitForSingleObject(oth->lock_sema, INFINITE);
|
||||
towrite = oth->buflen;
|
||||
if (towrite > (RKTIO_FD_BUFFSIZE - oth->bufstart))
|
||||
towrite = RKTIO_FD_BUFFSIZE - oth->bufstart;
|
||||
start = oth->bufstart;
|
||||
|
||||
ReleaseSemaphore(oth->lock_sema, 1, NULL);
|
||||
|
||||
ok = WriteFile(oth->fd, oth->buffer + start, towrite, &wrote, NULL);
|
||||
|
@ -1428,21 +1518,27 @@ static long WINAPI WindowsFDWriter(Win_FD_Output_Thread *oth)
|
|||
ReleaseSemaphore(oth->ready_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;
|
||||
}
|
||||
|
||||
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->work_sema);
|
||||
CloseHandle(oth->you_clean_up_sema);
|
||||
|
||||
CloseHandle(oth->fd);
|
||||
|
||||
if (close_mode != -1)
|
||||
CloseHandle(oth->fd);
|
||||
|
||||
if (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;
|
||||
}
|
||||
|
||||
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 (!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)) {
|
||||
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)) {
|
||||
SetFilePointer(fd, 0, NULL, FILE_END);
|
||||
if ((modes & (RKTIO_OPEN_APPEND |RKTIO_OPEN_TRUNCATE))
|
||||
&& rktio_fd_is_regular_file(rktio, rfd)) {
|
||||
if (modes & RKTIO_OPEN_APPEND)
|
||||
SetFilePointer(fd, 0, NULL, FILE_END);
|
||||
else
|
||||
SetEndOfFile(fd);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
int errid = 0;
|
||||
|
@ -830,6 +830,9 @@ int rktio_rename_file(rktio_t *rktio, const char *dest, const char *src, int exi
|
|||
return 1;
|
||||
}
|
||||
get_windows_error();
|
||||
} else if (errid == ERROR_ALREADY_EXISTS) {
|
||||
set_racket_error(RKTIO_ERROR_EXISTS);
|
||||
return 0;
|
||||
} else
|
||||
get_windows_error();
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#define RKTIO_SHUT_RD SHUT_RD
|
||||
#define RKTIO_SHUT_WR SHUT_WR
|
||||
|
||||
#define RKTIO_SOCKS(s) s
|
||||
|
||||
typedef intptr_t rktio_socket_t;
|
||||
typedef unsigned int rktio_sockopt_len_t;
|
||||
|
||||
|
@ -81,6 +83,9 @@ struct SOCKADDR_IN {
|
|||
typedef SOCKET rktio_socket_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;
|
||||
# define REGISTER_SOCKET(s) winsock_remember(s)
|
||||
# define UNREGISTER_SOCKET(s) winsock_forget(s)
|
||||
|
@ -858,9 +863,14 @@ void rktio_winsock_done(rktio_t *rktio)
|
|||
/* 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)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
|
||||
#ifdef RKTIO_SYSTEM_UNIX
|
||||
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
|
||||
#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;
|
||||
UNREGISTER_SOCKET(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)
|
||||
{
|
||||
#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);
|
||||
#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)
|
||||
{
|
||||
#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);
|
||||
#endif
|
||||
}
|
||||
|
||||
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))) {
|
||||
get_socket_error();
|
||||
|
@ -948,7 +958,7 @@ int rktio_socket_poll_write_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
#endif
|
||||
#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(exnfds);
|
||||
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_SET(s, exnfds);
|
||||
|
||||
sr = select(s + 1, NULL, writefds, exnfds, &time);
|
||||
sr = select(RKTIO_SOCKS(s + 1), NULL, writefds, exnfds, &time);
|
||||
|
||||
if (sr == -1) {
|
||||
get_socket_error();
|
||||
|
@ -982,7 +992,7 @@ int rktio_socket_poll_read_ready(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
#endif
|
||||
#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(exnfds);
|
||||
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_SET(s, exnfds);
|
||||
|
||||
sr = select(s + 1, readfds, NULL, exnfds, &time);
|
||||
sr = select(RKTIO_SOCKS(s + 1), readfds, NULL, exnfds, &time);
|
||||
|
||||
if (sr == -1) {
|
||||
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);
|
||||
#endif
|
||||
#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;
|
||||
intptr_t rc;
|
||||
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)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
int rn;
|
||||
|
||||
do {
|
||||
|
@ -1061,7 +1071,7 @@ static intptr_t do_socket_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buf
|
|||
/* for UDP sendto: */
|
||||
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;
|
||||
int errid = 0;
|
||||
|
||||
|
@ -1183,7 +1193,9 @@ static rktio_connect_t *try_connect(rktio_t *rktio, rktio_connect_t *conn)
|
|||
errno = status;
|
||||
#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;
|
||||
|
||||
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: */
|
||||
int 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) {
|
||||
errid = SOCK_ERRNO();
|
||||
} else
|
||||
|
@ -1541,7 +1553,7 @@ static int do_poll_accept_ready(rktio_t *rktio, rktio_listener_t *listener, int
|
|||
}
|
||||
|
||||
do {
|
||||
sr = select(mx + 1, RKTIO_SOCK_FDS(readfds), NULL, RKTIO_SOCK_FDS(exnfds), &time);
|
||||
sr = select(RKTIO_SOCKS(mx + 1), RKTIO_SOCK_FDS(readfds), NULL, RKTIO_SOCK_FDS(exnfds), &time);
|
||||
} while ((sr == -1) && NOT_WINSOCK(errno == EINTR));
|
||||
|
||||
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++) {
|
||||
s = listener->s[i];
|
||||
RKTIO_FD_SET(s, fds);
|
||||
RKTIO_FD_SET(s, fds2);
|
||||
RKTIO_FD_SET((intptr_t)s, fds);
|
||||
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;
|
||||
|
||||
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();
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1674,7 +1686,7 @@ char **rktio_socket_peer_address(rktio_t *rktio, rktio_fd_t *rfd)
|
|||
rktio_sockopt_len_t name_len;
|
||||
|
||||
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();
|
||||
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)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
int err;
|
||||
|
||||
#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)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
int err;
|
||||
|
||||
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)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
int err;
|
||||
|
||||
/* 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_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
rktio_length_and_addrinfo_t *r;
|
||||
int rn, errid;
|
||||
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)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
u_char loop;
|
||||
rktio_sockopt_len_t loop_len = sizeof(loop);
|
||||
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)
|
||||
{
|
||||
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);
|
||||
rktio_sockopt_len_t loop_len = sizeof(loop);
|
||||
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)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
u_char ttl;
|
||||
rktio_sockopt_len_t ttl_len = sizeof(ttl);
|
||||
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)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
u_char ttl = ttl_val;
|
||||
rktio_sockopt_len_t ttl_len = sizeof(ttl);
|
||||
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)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
struct in_addr intf;
|
||||
rktio_sockopt_len_t intf_len = sizeof(intf);
|
||||
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)
|
||||
{
|
||||
rktio_socket_t s = rktio_fd_system_fd(rktio, rfd);
|
||||
rktio_socket_t s = rktio_fd_socket(rktio, rfd);
|
||||
struct in_addr intf;
|
||||
rktio_sockopt_len_t intf_len = sizeof(intf);
|
||||
int status;
|
||||
|
@ -1964,7 +1976,7 @@ int rktio_udp_change_multicast_group(rktio_t *rktio, rktio_fd_t *rfd,
|
|||
rktio_addrinfo_t *intf_addr,
|
||||
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;
|
||||
rktio_sockopt_len_t mreq_len = sizeof(mreq);
|
||||
int status;
|
||||
|
|
|
@ -26,7 +26,7 @@ static int MyPipe(intptr_t *ph, int flags, rktio_t *rktio)
|
|||
a[1] = w;
|
||||
|
||||
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
|
||||
close the inheritable one: */
|
||||
if (!DuplicateHandle(GetCurrentProcess(), a[near_index],
|
||||
|
|
|
@ -94,7 +94,7 @@ void rktio_fdzero(rktio_poll_set_t *fd)
|
|||
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 i;
|
||||
|
@ -111,7 +111,7 @@ static int find_fd_pos(struct rktio_fd_set_data_t *data, int n)
|
|||
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;
|
||||
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;
|
||||
intptr_t flag = fd->flags;
|
||||
|
@ -157,7 +157,7 @@ void rktio_fdset(rktio_poll_set_t *fd, int n)
|
|||
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;
|
||||
intptr_t flag = fd->flags;
|
||||
|
@ -469,27 +469,27 @@ void rktio_fdzero(rktio_poll_set_t *fd)
|
|||
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--; ) {
|
||||
if (fd->sockets[i] == n)
|
||||
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) {
|
||||
int na;
|
||||
intptr_t na;
|
||||
na = next_size(fd->last_alloc);
|
||||
fd->last_alloc = na;
|
||||
}
|
||||
if (fd->added >= fd->alloc) {
|
||||
SOCKET *naya;
|
||||
int na;
|
||||
intptr_t na;
|
||||
na = next_size(fd->alloc);
|
||||
naya = malloc(na * 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;
|
||||
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--; ) {
|
||||
if (fd->sockets[i] == n)
|
||||
if (fd->sockets[i] == (SOCKET)n)
|
||||
return 1;
|
||||
}
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
intptr_t i;
|
||||
for (i = src_fds->added; i--; ) {
|
||||
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;
|
||||
rktio_poll_set_t *efd = fds;
|
||||
HANDLE *hs;
|
||||
int i, new_i, *rps;
|
||||
intptr_t i, new_i;
|
||||
int *rps;
|
||||
|
||||
if (efd->num_handles == 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;
|
||||
HANDLE *wa, e;
|
||||
int i, p = 0, mask, j;
|
||||
intptr_t i, p = 0, mask, j;
|
||||
SOCKET s;
|
||||
|
||||
rfd = fds;
|
||||
|
@ -781,12 +782,12 @@ static int fdset_has_nosleep(rktio_poll_set_t *fds)
|
|||
|
||||
#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);
|
||||
}
|
||||
|
||||
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
|
||||
int mx;
|
||||
|
@ -797,7 +798,7 @@ void rktio_fdset(rktio_poll_set_t *fd, int n)
|
|||
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);
|
||||
}
|
||||
|
@ -1207,7 +1208,8 @@ void rktio_sleep(rktio_t *rktio, float nsecs, rktio_poll_set_t *fds, rktio_ltps_
|
|||
{
|
||||
intptr_t result;
|
||||
HANDLE *array, just_two_array[2];
|
||||
int count, rcount, *rps;
|
||||
intptr_t count, rcount;
|
||||
int *rps;
|
||||
|
||||
rktio_collapse_win_fd(fds); /* merges */
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
/*========================================================================*/
|
||||
|
||||
struct rktio_t {
|
||||
intptr_t errid;
|
||||
int errid;
|
||||
int errkind;
|
||||
#ifdef RKTIO_SYSTEM_WINDOWS
|
||||
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);
|
||||
void rktio_fdzero(rktio_poll_set_t *fd);
|
||||
void rktio_fdset(rktio_poll_set_t *fd, int n);
|
||||
void rktio_fdclr(rktio_poll_set_t *fd, int n);
|
||||
int rktio_fdisset(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, intptr_t n);
|
||||
int rktio_fdisset(rktio_poll_set_t *fd, intptr_t n);
|
||||
|
||||
# define DECL_FDSET(n, c) rktio_poll_set_t *n
|
||||
# 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,
|
||||
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 new_process_group, int chain_termination_here_to_child,
|
||||
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;
|
||||
char *cmdline;
|
||||
wchar_t *cmdline_w, *wd_w;
|
||||
|
@ -1043,14 +1044,14 @@ static intptr_t do_spawnv(rktio_t *rktio,
|
|||
if (exact_cmdline) {
|
||||
cmdline = (char *)argv[1];
|
||||
} else {
|
||||
for (i = 0; argv[i]; i++) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
len += strlen(argv[i]) + 1;
|
||||
}
|
||||
|
||||
cmdline = malloc(len);
|
||||
|
||||
len = 0;
|
||||
for (i = 0; argv[i]; i++) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
l = strlen(argv[i]);
|
||||
memcpy(cmdline + len, argv[i], 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 i;
|
||||
#endif
|
||||
|
||||
|
||||
/* avoid compiler warnings: */
|
||||
to_subprocess[0] = -1;
|
||||
to_subprocess[1] = -1;
|
||||
|
@ -1228,8 +1229,8 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
|
|||
if (stdin_fd) {
|
||||
to_subprocess[0] = rktio_fd_system_fd(rktio, stdin_fd);
|
||||
RKTIO_COPY_FOR_SUBPROCESS(to_subprocess, 0);
|
||||
} else if (rktio_make_os_pipe(rktio, to_subprocess, 1)) {
|
||||
if (stdout_fd) { RKTIO_CLOSE_SUBPROCESS_COPY(from_subprocess, RKTIO_NO_INHERIT_OUTPUT); }
|
||||
} else if (rktio_make_os_pipe(rktio, to_subprocess, RKTIO_NO_INHERIT_OUTPUT)) {
|
||||
if (stdout_fd) { RKTIO_CLOSE_SUBPROCESS_COPY(from_subprocess, 1); }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1276,7 +1277,7 @@ rktio_process_result_t *rktio_process(rktio_t *rktio,
|
|||
pid = 0;
|
||||
|
||||
spawn_status = do_spawnv(rktio,
|
||||
command, (const char * const *)argv,
|
||||
command, argc, (const char * const *)argv,
|
||||
windows_exact_cmdline,
|
||||
to_subprocess[0],
|
||||
from_subprocess[1],
|
||||
|
|
2
racket/src/worksp/.gitignore
vendored
2
racket/src/worksp/.gitignore
vendored
|
@ -13,6 +13,8 @@
|
|||
*/*.suo
|
||||
*/*.sdf
|
||||
*/*.sln.cache
|
||||
*/*.db
|
||||
*/.vs
|
||||
|
||||
# potentially generated by "genvsx"
|
||||
*/*X.vcxproj
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
OutputDirectory="$(SolutionDir)\..\libffi\$(ConfigurationName)"
|
||||
IntermediateDirectory="..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
>
|
||||
|
@ -41,8 +41,8 @@
|
|||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
OutputDirectory="$(SolutionDir)\..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
>
|
||||
|
@ -61,8 +61,8 @@
|
|||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
OutputDirectory="$(SolutionDir)\..\libffi\$(ConfigurationName)"
|
||||
IntermediateDirectory="..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
|
@ -82,8 +82,8 @@
|
|||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
OutputDirectory="$(SolutionDir)\..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="..\libffi\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||
<TargetName>libffi</TargetName>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<OutDir>$(SolutionDir)\..\libffi\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>..\libffi\$(Platform)\$(Configuration)\</IntDir>
|
||||
<PlatformToolset>v100</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
OutputDirectory="$(SolutionDir)\..\librktio\$(ConfigurationName)"
|
||||
IntermediateDirectory="..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
>
|
||||
|
@ -41,8 +41,8 @@
|
|||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|x64"
|
||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
OutputDirectory="$(SolutionDir)\..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
>
|
||||
|
@ -61,8 +61,8 @@
|
|||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
OutputDirectory="$(SolutionDir)\..\librktio\$(ConfigurationName)"
|
||||
IntermediateDirectory="..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
|
@ -82,8 +82,8 @@
|
|||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|x64"
|
||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
|
||||
OutputDirectory="$(SolutionDir)\..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||
IntermediateDirectory="..\librktio\$(PlatformName)\$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||
<TargetName>librktio</TargetName>
|
||||
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(Platform)\$(Configuration)\</IntDir>
|
||||
<OutDir>$(SolutionDir)\..\librktio\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>..\librktio\$(Platform)\$(Configuration)\</IntDir>
|
||||
<PlatformToolset>v100</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
|
|
|
@ -2,5 +2,8 @@
|
|||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef _int64 rktio_int64_t;
|
||||
typedef unsigned _int64 rktio_uint64_t;
|
||||
|
||||
/* whether getaddrinfo works */
|
||||
#define HAVE_GETADDRINFO 1
|
||||
|
|
Loading…
Reference in New Issue
Block a user