diff --git a/racket/src/racket/main.c b/racket/src/racket/main.c index 6e83cbe344..6a9d05e7a5 100644 --- a/racket/src/racket/main.c +++ b/racket/src/racket/main.c @@ -62,7 +62,9 @@ START_XFORM_SUSPEND; #endif #include -#include +#ifndef DOS_FILE_SYSTEM +# include +#endif #ifndef NO_USER_BREAK_HANDLER # include #endif diff --git a/racket/src/racket/src/salloc.c b/racket/src/racket/src/salloc.c index e028f0d004..c6ae86bc51 100644 --- a/racket/src/racket/src/salloc.c +++ b/racket/src/racket/src/salloc.c @@ -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 diff --git a/racket/src/rktio/demo.c b/racket/src/rktio/demo.c index 54d7b43781..00ee64528c 100644 --- a/racket/src/rktio/demo.c +++ b/racket/src/rktio/demo.c @@ -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) diff --git a/racket/src/rktio/make32.bat b/racket/src/rktio/make32.bat new file mode 100644 index 0000000000..e62f232cee --- /dev/null +++ b/racket/src/rktio/make32.bat @@ -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 diff --git a/racket/src/rktio/make64.bat b/racket/src/rktio/make64.bat new file mode 100644 index 0000000000..813175453e --- /dev/null +++ b/racket/src/rktio/make64.bat @@ -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 diff --git a/racket/src/rktio/rktio.h b/racket/src/rktio/rktio.h index 4f7cd6eb70..8e8a974cf6 100644 --- a/racket/src/rktio/rktio.h +++ b/racket/src/rktio/rktio.h @@ -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 */ diff --git a/racket/src/rktio/rktio_envvars.c b/racket/src/rktio/rktio_envvars.c index 09367c2e4f..bbfa8d06d2 100644 --- a/racket/src/rktio/rktio_envvars.c +++ b/racket/src/rktio/rktio_envvars.c @@ -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; diff --git a/racket/src/rktio/rktio_error.c b/racket/src/rktio/rktio_error.c index ba8d765c08..0d7181d221 100644 --- a/racket/src/rktio/rktio_error.c +++ b/racket/src/rktio/rktio_error.c @@ -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 diff --git a/racket/src/rktio/rktio_fd.c b/racket/src/rktio/rktio_fd.c index 8a88f398e6..260b982552 100644 --- a/racket/src/rktio/rktio_fd.c +++ b/racket/src/rktio/rktio_fd.c @@ -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); diff --git a/racket/src/rktio/rktio_file.c b/racket/src/rktio/rktio_file.c index a27f94f46c..734e6e8c54 100644 --- a/racket/src/rktio/rktio_file.c +++ b/racket/src/rktio/rktio_file.c @@ -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; diff --git a/racket/src/rktio/rktio_fs.c b/racket/src/rktio/rktio_fs.c index 41c0f48ad8..84313b434b 100644 --- a/racket/src/rktio/rktio_fs.c +++ b/racket/src/rktio/rktio_fs.c @@ -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(); diff --git a/racket/src/rktio/rktio_network.c b/racket/src/rktio/rktio_network.c index 7a07785146..e4d97e4b42 100644 --- a/racket/src/rktio/rktio_network.c +++ b/racket/src/rktio/rktio_network.c @@ -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; diff --git a/racket/src/rktio/rktio_pipe.c b/racket/src/rktio/rktio_pipe.c index a4fdb3b279..9ad9958c88 100644 --- a/racket/src/rktio/rktio_pipe.c +++ b/racket/src/rktio/rktio_pipe.c @@ -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], diff --git a/racket/src/rktio/rktio_poll_set.c b/racket/src/rktio/rktio_poll_set.c index c5c7dbc49b..cec64de0d5 100644 --- a/racket/src/rktio/rktio_poll_set.c +++ b/racket/src/rktio/rktio_poll_set.c @@ -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 */ diff --git a/racket/src/rktio/rktio_private.h b/racket/src/rktio/rktio_private.h index f0249459ca..959e83c3ee 100644 --- a/racket/src/rktio/rktio_private.h +++ b/racket/src/rktio/rktio_private.h @@ -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) { \ diff --git a/racket/src/rktio/rktio_process.c b/racket/src/rktio/rktio_process.c index 6e855ffc7d..a13ebb298d 100644 --- a/racket/src/rktio/rktio_process.c +++ b/racket/src/rktio/rktio_process.c @@ -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], diff --git a/racket/src/worksp/.gitignore b/racket/src/worksp/.gitignore index 0b53f3d0b8..c3b42dae89 100644 --- a/racket/src/worksp/.gitignore +++ b/racket/src/worksp/.gitignore @@ -13,6 +13,8 @@ */*.suo */*.sdf */*.sln.cache +*/*.db +*/.vs # potentially generated by "genvsx" */*X.vcxproj diff --git a/racket/src/worksp/libffi/libffi.vcproj b/racket/src/worksp/libffi/libffi.vcproj index 838a33a2e9..deede22a4f 100644 --- a/racket/src/worksp/libffi/libffi.vcproj +++ b/racket/src/worksp/libffi/libffi.vcproj @@ -21,8 +21,8 @@ @@ -41,8 +41,8 @@ @@ -61,8 +61,8 @@ <_ProjectFileVersion>10.0.40219.1 libffi - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ + $(SolutionDir)\..\libffi\$(Platform)\$(Configuration)\ + ..\libffi\$(Platform)\$(Configuration)\ v100 diff --git a/racket/src/worksp/librktio/librktio.vcproj b/racket/src/worksp/librktio/librktio.vcproj index f2e351ee7a..d0c7689fb6 100644 --- a/racket/src/worksp/librktio/librktio.vcproj +++ b/racket/src/worksp/librktio/librktio.vcproj @@ -21,8 +21,8 @@ @@ -41,8 +41,8 @@ @@ -61,8 +61,8 @@ <_ProjectFileVersion>10.0.40219.1 librktio - $(SolutionDir)$(Platform)\$(Configuration)\ - $(Platform)\$(Configuration)\ + $(SolutionDir)\..\librktio\$(Platform)\$(Configuration)\ + ..\librktio\$(Platform)\$(Configuration)\ v100 diff --git a/racket/src/worksp/librktio/rktio_config.h b/racket/src/worksp/librktio/rktio_config.h index 948ddd8da9..6fdc5674f3 100644 --- a/racket/src/worksp/librktio/rktio_config.h +++ b/racket/src/worksp/librktio/rktio_config.h @@ -2,5 +2,8 @@ #include +typedef _int64 rktio_int64_t; +typedef unsigned _int64 rktio_uint64_t; + /* whether getaddrinfo works */ #define HAVE_GETADDRINFO 1