diff --git a/racket/src/cs/c/main.c b/racket/src/cs/c/main.c index df480da448..3807b388d2 100644 --- a/racket/src/cs/c/main.c +++ b/racket/src/cs/c/main.c @@ -144,8 +144,12 @@ static char *get_self_path() } static int scheme_utf8_encode(unsigned int *path, int zero_offset, int len, - char *dest, int dest_len, int get_utf16) + char *dest, int offset, int get_utf16) { + int dest_len = 0; + if (dest) { + dest_len = WideCharToMultiByte(CP_UTF8, 0, (wchar_t *)path, len, NULL, 0, NULL, NULL); + } return WideCharToMultiByte(CP_UTF8, 0, (wchar_t *)path, len, dest, dest_len, NULL, NULL); } diff --git a/racket/src/gracket/grmain.c b/racket/src/gracket/grmain.c index 2e4353223f..5afe7ae0c1 100644 --- a/racket/src/gracket/grmain.c +++ b/racket/src/gracket/grmain.c @@ -11,7 +11,6 @@ /* Hack: overwrite "y" with "n" in binary to disable checking for another instance of the same app. */ char *check_for_another = "yes, please check for another"; -static int wx_in_terminal = 0; # define MZ_DEFINE_UTF8_MAIN # define PRE_FILTER_CMDLINE_ARGUMENTS static void pre_filter_cmdline_arguments(int *argc, char ***argv); @@ -69,104 +68,28 @@ static void pre_filter_cmdline_arguments(int *argc, char ***argv); #ifdef WIN32 -/* ---------------------------------------- */ -/* stdio to console */ -/* ---------------------------------------- */ +# ifdef MZ_PRECISE_GC +START_XFORM_SKIP; +# endif -static void MrEdSchemeMessages(char *, ...); -static Scheme_Object *stdin_pipe; +# include "../start/win_single.inc" -static HANDLE console_out; -static HANDLE console_in; -static Scheme_Object *console_inport; -static HWND console_hwnd; -static int has_stdio, stdio_kills_prog; -static HANDLE waiting_sema; -static void *orig_signal_handle; -static void *orig_break_handle; - -typedef HWND (WINAPI* gcw_proc)(); - -static void init_console_in() +static void pre_filter_cmdline_arguments(int *argc, char ***argv) { - if (!console_in) { - console_in = GetStdHandle(STD_INPUT_HANDLE); - MZ_REGISTER_STATIC(console_inport); - console_inport = scheme_make_fd_input_port((intptr_t)console_in, scheme_intern_symbol("stdin"), 0, 0); - } -} - -static BOOL WINAPI ConsoleHandler(DWORD op) -{ - if (stdio_kills_prog) { - ReleaseSemaphore(waiting_sema, 1, NULL); - } else { - scheme_break_main_thread_at(orig_break_handle); - scheme_signal_received_at(orig_signal_handle); - } - return TRUE; -} - -static void WaitOnConsole() -{ - DWORD wrote; - - stdio_kills_prog = 1; - if (console_hwnd) { - AppendMenu(GetSystemMenu(console_hwnd, FALSE), - MF_STRING, - SC_CLOSE, - "Close"); - /* Un-gray the close box: */ - RedrawWindow(console_hwnd, NULL, NULL, - RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); - } - - WriteConsole(console_out, "\n[Exited. Close box or Ctrl-C closes the console.]\n", 51, &wrote, NULL); - - WaitForSingleObject(waiting_sema, INFINITE); + scheme_register_process_global("PLT_WM_IS_GRACKET", (void *)(intptr_t)wm_is_gracket); + scheme_register_process_global("PLT_GRACKET_GUID", GRACKET_GUID); } static void MrEdSchemeMessages(char *msg, ...) { - GC_CAN_IGNORE va_list args; + HANDLE console_out; + va_list args; + + scheme_ensure_console_ready(); - scheme_start_atomic(); + va_start(args, msg); - XFORM_HIDE_EXPR(va_start(args, msg)); - - if (!console_out) { - AllocConsole(); - console_out = GetStdHandle(STD_OUTPUT_HANDLE); - - if (!wx_in_terminal) { - has_stdio = 1; - waiting_sema = CreateSemaphore(NULL, 0, 1, NULL); - orig_signal_handle = scheme_get_signal_handle(); - orig_break_handle = scheme_get_main_thread_break_handle(); - SetConsoleCtrlHandler(ConsoleHandler, TRUE); - - { - HMODULE hm; - gcw_proc gcw; - - hm = LoadLibrary("kernel32.dll"); - if (hm) - gcw = (gcw_proc)GetProcAddress(hm, "GetConsoleWindow"); - else - gcw = NULL; - - if (gcw) - console_hwnd = gcw(); - } - - if (console_hwnd) { - EnableMenuItem(GetSystemMenu(console_hwnd, FALSE), SC_CLOSE, - MF_BYCOMMAND | MF_GRAYED); - RemoveMenu(GetSystemMenu(console_hwnd, FALSE), SC_CLOSE, MF_BYCOMMAND); - } - } - } + console_out = GetStdHandle(STD_OUTPUT_HANDLE); if (!msg) { char *s; @@ -190,9 +113,7 @@ static void MrEdSchemeMessages(char *msg, ...) free(buffer); } - scheme_end_atomic_no_swap(); - - XFORM_HIDE_EXPR(va_end(args)); + va_end(args); } static void MrEdSchemeMessagesOutput(char *s, intptr_t l) @@ -201,232 +122,13 @@ static void MrEdSchemeMessagesOutput(char *s, intptr_t l) MrEdSchemeMessages(NULL, s, 0, l); } -static Scheme_Object *console_reading; - -static void add_console_reading() -{ - Scheme_Thread *thread; - thread = scheme_get_current_thread(); - - if (!console_reading) { - MZ_REGISTER_STATIC(console_reading); - console_reading = scheme_make_null(); - } - - console_reading = scheme_make_pair((Scheme_Object *)thread, - console_reading); -} - -static void remove_console_reading() -{ - Scheme_Object *p, *prev = NULL; - Scheme_Thread *thread; - thread = scheme_get_current_thread(); - - if (!console_reading) - return; - - p = console_reading; - while (SCHEME_PAIRP(p)) { - if (SAME_OBJ(SCHEME_CAR(p), (Scheme_Object *)thread)) { - if (prev) - SCHEME_CDR(prev) = SCHEME_CDR(p); - else - console_reading = SCHEME_CDR(p); - return; - } - prev = p; - p = SCHEME_CDR(p); - } -} - -static void break_console_reading_threads() -{ - Scheme_Object *p; - - if (!console_reading) - return; - - for (p = console_reading; SCHEME_PAIRP(p); p = SCHEME_CDR(p)) { - scheme_break_thread((Scheme_Thread *)SCHEME_CAR(p)); - } -} - -static intptr_t mrconsole_get_string(Scheme_Input_Port *ip, - char *buffer, intptr_t offset, intptr_t size, - int nonblock, Scheme_Object *unless) -{ - intptr_t result; - Scheme_Object *pipe = (Scheme_Object *)ip->port_data; - - if (!pipe) return 0; - MrEdSchemeMessages(""); - - init_console_in(); - pipe = console_inport; - - add_console_reading(); - result = scheme_get_byte_string_unless("console get-string", pipe, - buffer, offset, size, - nonblock, 0, NULL, - unless); - remove_console_reading(); - return result; -} - -static Scheme_Object *mrconsole_progress_evt(Scheme_Input_Port *ip) -{ - Scheme_Object *pipe = (Scheme_Object *)ip->port_data; - - if (!pipe) return NULL; - MrEdSchemeMessages(""); - - init_console_in(); - pipe = console_inport; - - return scheme_progress_evt(pipe); -} - -static int mrconsole_peeked_read(Scheme_Input_Port *ip, - intptr_t amount, - Scheme_Object *unless, - Scheme_Object *target_ch) -{ - Scheme_Object *pipe = (Scheme_Object *)ip->port_data; - - if (!pipe) return 0; - MrEdSchemeMessages(""); - - init_console_in(); - pipe = console_inport; - - return scheme_peeked_read(pipe, amount, unless, target_ch); -} - -static int mrconsole_char_ready(Scheme_Input_Port *ip) -{ - Scheme_Object *pipe = (Scheme_Object *)ip->port_data; - - if (!pipe) return 0; - MrEdSchemeMessages(""); - - init_console_in(); - pipe = console_inport; - - return scheme_char_ready(pipe); -} - -static void mrconsole_close(Scheme_Input_Port *ip) -{ - Scheme_Object *pipe = (Scheme_Object *)ip->port_data; - - if (!pipe) return; - - init_console_in(); - pipe = console_inport; - - scheme_close_input_port(pipe); -} - -static Scheme_Object *MrEdMakeStdIn(void) -{ - Scheme_Object *readp; - Scheme_Input_Port *ip; - - if (scheme_get_place_id() == 0) { - MZ_REGISTER_STATIC(stdin_pipe); - - scheme_pipe(&readp, &stdin_pipe); - } else { - /* for a non-main place, the port will be replaced anyway */ - readp = NULL; - } - - ip = scheme_make_input_port(scheme_make_port_type("mred-console-input-port"), - readp, - scheme_intern_symbol("mred-console"), - mrconsole_get_string, - NULL, - mrconsole_progress_evt, - mrconsole_peeked_read, - mrconsole_char_ready, - mrconsole_close, - NULL, - 0); - - return (Scheme_Object *)ip; -} - -static intptr_t stdout_write(Scheme_Output_Port*op, const char *s, intptr_t d, intptr_t l, - int rarely_block, int enable_break) -{ - if (l) - MrEdSchemeMessages(NULL, s, d, l); - return l; -} - -static Scheme_Object *MrEdMakeStdOut(void) -{ - Scheme_Object *outtype; - - outtype = scheme_make_port_type("stdout"); - - return (Scheme_Object *)scheme_make_output_port(outtype, NULL, - scheme_intern_symbol("mred-console"), - scheme_write_evt_via_write, - stdout_write, - NULL, NULL, NULL, NULL, NULL, 0); -} - -static intptr_t stderr_write(Scheme_Output_Port*op, const char *s, intptr_t d, intptr_t l, - int rarely_block, int enable_break) -{ - if (l) - MrEdSchemeMessages(NULL, s, d, l); - return l; -} - -static Scheme_Object *MrEdMakeStdErr(void) -{ - Scheme_Object *errtype; - - errtype = scheme_make_port_type("stderr"); - - return (Scheme_Object *)scheme_make_output_port(errtype, NULL, - scheme_intern_symbol("mred-console"), - scheme_write_evt_via_write, - stderr_write, - NULL, NULL, NULL, NULL, NULL, 0); -} - -static void MrEdExit(int v) -{ - if (has_stdio) { - WaitOnConsole(); - } - - scheme_immediate_exit(v); -} - -# ifdef MZ_PRECISE_GC -START_XFORM_SKIP; -# endif - -# include "../start/win_single.inc" - -static void pre_filter_cmdline_arguments(int *argc, char ***argv) -{ - scheme_register_process_global("PLT_WM_IS_GRACKET", (void *)(intptr_t)wm_is_gracket); - scheme_register_process_global("PLT_GRACKET_GUID", GRACKET_GUID); -} - /* ---------------------------------------- */ /* command-line parsing */ /* ---------------------------------------- */ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ignored, int nCmdShow) { - int j, argc; + int j, argc, in_terminal = 0; char **argv, *normalized_path; load_delayed(); @@ -436,7 +138,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ignored h = GetStdHandle(STD_OUTPUT_HANDLE); if (h && (h != INVALID_HANDLE_VALUE) && (GetFileType(h) != FILE_TYPE_UNKNOWN)) { - wx_in_terminal = 1; + in_terminal = 1; } } @@ -445,18 +147,13 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR ignored if (CheckSingleInstance(normalized_path, argv)) return 0; - if (!wx_in_terminal) { - scheme_set_stdio_makers(MrEdMakeStdIn, - MrEdMakeStdOut, - MrEdMakeStdErr); + if (!in_terminal) scheme_set_console_output(MrEdSchemeMessagesOutput); - } scheme_set_console_printf(MrEdSchemeMessages); - scheme_set_exit(MrEdExit); j = MAIN(argc, argv); - MrEdExit(j); + scheme_immediate_exit(j); /* shouldn't get here */ return j; diff --git a/racket/src/racket/include/scheme.h b/racket/src/racket/include/scheme.h index b5f9956b25..4021c25727 100644 --- a/racket/src/racket/include/scheme.h +++ b/racket/src/racket/include/scheme.h @@ -1883,6 +1883,7 @@ MZ_EXTERN void scheme_set_console_printf(scheme_console_printf_t p); typedef void (*scheme_console_output_t)(char *str, intptr_t len); MZ_EXTERN scheme_console_output_t scheme_console_output; MZ_EXTERN void scheme_set_console_output(scheme_console_output_t p); +MZ_EXTERN void scheme_ensure_console_ready(); MZ_EXTERN void (*scheme_sleep)(float seconds, void *fds); MZ_EXTERN void (*scheme_notify_multithread)(int on); MZ_EXTERN void (*scheme_wakeup_on_input)(void *fds); diff --git a/racket/src/racket/src/error.c b/racket/src/racket/src/error.c index 2938fc0b01..ec028a1a5a 100644 --- a/racket/src/racket/src/error.c +++ b/racket/src/racket/src/error.c @@ -1136,6 +1136,11 @@ void scheme_warning(char *msg, ...) scheme_get_param(scheme_current_config(), MZCONFIG_ERROR_PORT)); } +void scheme_ensure_console_ready() +{ + rktio_create_console(); +} + void scheme_log(Scheme_Logger *logger, int level, int flags, const char *msg, ...) { diff --git a/racket/src/racket/src/port.c b/racket/src/racket/src/port.c index b0d11aa8ab..9c0b688728 100644 --- a/racket/src/racket/src/port.c +++ b/racket/src/racket/src/port.c @@ -3617,8 +3617,10 @@ Scheme_Object *scheme_terminal_port_p(int argc, Scheme_Object *argv[]) fd_ok = 1; } else if (SAME_OBJ(ip->sub_type, fd_input_port_type)) { - fd = rktio_fd_system_fd(scheme_rktio, ((Scheme_FD *)ip->port_data)->fd); - fd_ok = 1; + if (rktio_fd_is_terminal(scheme_rktio, ((Scheme_FD *)ip->port_data)->fd)) + return scheme_true; + else + return scheme_false; } } else if (SCHEME_OUTPUT_PORTP(p)) { Scheme_Output_Port *op; @@ -3633,8 +3635,10 @@ Scheme_Object *scheme_terminal_port_p(int argc, Scheme_Object *argv[]) fd_ok = 1; } else if (SAME_OBJ(op->sub_type, fd_output_port_type)) { - fd = rktio_fd_system_fd(scheme_rktio, ((Scheme_FD *)op->port_data)->fd); - fd_ok = 1; + if (rktio_fd_is_terminal(scheme_rktio, ((Scheme_FD *)op->port_data)->fd)) + return scheme_true; + else + return scheme_false; } } diff --git a/racket/src/rktio/Makefile.in b/racket/src/rktio/Makefile.in index 02384a3d97..e18ddf2387 100644 --- a/racket/src/rktio/Makefile.in +++ b/racket/src/rktio/Makefile.in @@ -47,6 +47,7 @@ OBJS = rktio_fs.@LTO@ \ rktio_error.@LTO@ \ rktio_hash.@LTO@ \ rktio_wide.@LTO@ \ + rktio_console.@LTO@ \ rktio_main.@LTO@ default_rktio: @@ -137,6 +138,9 @@ rktio_hash.@LTO@: $(srcdir)/rktio_hash.c $(RKTIO_HEADERS) rktio_wide.@LTO@: $(srcdir)/rktio_wide.c $(RKTIO_HEADERS) $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_wide.@LTO@ -c $(srcdir)/rktio_wide.c +rktio_console.@LTO@: $(srcdir)/rktio_console.c $(RKTIO_HEADERS) + $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_console.@LTO@ -c $(srcdir)/rktio_console.c + rktio_main.@LTO@: $(srcdir)/rktio_main.c $(RKTIO_HEADERS) $(CC) $(CFLAGS) -I$(srcdir) -I. -o rktio_main.@LTO@ -c $(srcdir)/rktio_main.c diff --git a/racket/src/rktio/rktio.h b/racket/src/rktio/rktio.h index d41dae619f..6153c7dca8 100644 --- a/racket/src/rktio/rktio.h +++ b/racket/src/rktio/rktio.h @@ -245,6 +245,13 @@ RKTIO_EXTERN rktio_fd_t *rktio_std_fd(rktio_t *rktio, int which); #define RKTIO_STDOUT 1 #define RKTIO_STDERR 2 +RKTIO_EXTERN void rktio_create_console(); +/* On Windows, ensures that a console is available for output. If a + console is created for an application started in GUI mode, The + console cannot be closed by the user until the process exits, and + then an atexit callback pauses the exit until the user closes the + console. */ + RKTIO_EXTERN_ERR(RKTIO_READ_ERROR) intptr_t rktio_read(rktio_t *rktio, rktio_fd_t *fd, char *buffer, intptr_t len); /* Returns the number of bytes read, possibly 0, in non-blocking mode. diff --git a/racket/src/rktio/rktio_console.c b/racket/src/rktio/rktio_console.c new file mode 100644 index 0000000000..50babaa845 --- /dev/null +++ b/racket/src/rktio/rktio_console.c @@ -0,0 +1,86 @@ +#include "rktio.h" +#include "rktio_private.h" + +#ifdef RKTIO_SYSTEM_UNIX + +void rktio_create_console() +{ +} + +#endif + +#ifdef RKTIO_SYSTEM_WINDOWS + +static int has_console; +static HWND console_hwnd; +static HANDLE waiting_sema; +typedef HWND (WINAPI* gcw_proc)(); + +void rktio_console_ctl_c() +{ + if (waiting_sema) + ReleaseSemaphore(waiting_sema, 1, NULL); +} + +static void WaitOnConsole() +{ + DWORD wrote; + + if (!has_console) + return; + + waiting_sema = CreateSemaphore(NULL, 0, 1, NULL); + + if (console_hwnd) { + AppendMenu(GetSystemMenu(console_hwnd, FALSE), + MF_STRING, + SC_CLOSE, + "Close"); + /* Un-gray the close box: */ + RedrawWindow(console_hwnd, NULL, NULL, + RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW); + } + + WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), + L"\n[Exited. Close box or Ctrl-C closes the console.]\n", + 51, + &wrote, + NULL); + + WaitForSingleObject(waiting_sema, INFINITE); + + has_console = 0; +} + +void rktio_create_console() +{ + if (!has_console) { + HMODULE hm; + gcw_proc gcw; + + AllocConsole(); + + rktio_set_console_handler(); + + hm = LoadLibraryW(L"kernel32.dll"); + if (hm) + gcw = (gcw_proc)GetProcAddress(hm, "GetConsoleWindow"); + else + gcw = NULL; + + if (gcw) + console_hwnd = gcw(); + + if (console_hwnd) { + EnableMenuItem(GetSystemMenu(console_hwnd, FALSE), SC_CLOSE, + MF_BYCOMMAND | MF_GRAYED); + RemoveMenu(GetSystemMenu(console_hwnd, FALSE), SC_CLOSE, MF_BYCOMMAND); + } + + has_console = 1; + + atexit(WaitOnConsole); + } +} + +#endif diff --git a/racket/src/rktio/rktio_fd.c b/racket/src/rktio/rktio_fd.c index 0b7cbbfb64..ef34f74cbc 100644 --- a/racket/src/rktio/rktio_fd.c +++ b/racket/src/rktio/rktio_fd.c @@ -103,6 +103,9 @@ static void deinit_fd(rktio_fd_t *rfd, int full_close) deinit_write_fd(rfd, full_close); } +#define DELAYED_CONSOLE_HANDLE ((HANDLE)-2) +static void force_console(rktio_fd_t *rfd); + static long WINAPI WindowsFDReader(Win_FD_Input_Thread *th); static void WindowsFDICleanup(Win_FD_Input_Thread *th, int close_mode); @@ -174,7 +177,8 @@ rktio_fd_t *rktio_system_fd(rktio_t *rktio, intptr_t system_fd, int modes) rfd->sock = (SOCKET)system_fd; else rfd->fd = (HANDLE)system_fd; - if (!(modes & (RKTIO_OPEN_REGFILE | RKTIO_OPEN_NOT_REGFILE | RKTIO_OPEN_SOCKET))) { + if (!(modes & (RKTIO_OPEN_REGFILE | RKTIO_OPEN_NOT_REGFILE | RKTIO_OPEN_SOCKET)) + && (rfd->fd != DELAYED_CONSOLE_HANDLE)) { if ((GetFileType(rfd->fd) == FILE_TYPE_DISK)) rfd->modes |= RKTIO_OPEN_REGFILE; if (!(modes & (RKTIO_OPEN_DIR | RKTIO_OPEN_NOT_DIR))) { @@ -205,8 +209,10 @@ intptr_t rktio_internal_fd_system_fd(rktio_fd_t *rfd) #ifdef RKTIO_SYSTEM_WINDOWS if (rfd->modes & RKTIO_OPEN_SOCKET) return (intptr_t)rfd->sock; - else + else { + force_console(rfd); return (intptr_t)rfd->fd; + } #endif } @@ -224,6 +230,7 @@ rktio_fd_t *rktio_std_fd(rktio_t *rktio, int which) return rktio_system_fd(rktio, which, mode | RKTIO_OPEN_NOT_DIR); #endif #ifdef RKTIO_SYSTEM_WINDOWS + HANDLE h; switch (which) { case RKTIO_STDIN: which = STD_INPUT_HANDLE; @@ -235,8 +242,12 @@ rktio_fd_t *rktio_std_fd(rktio_t *rktio, int which) which = STD_ERROR_HANDLE; break; } + h = GetStdHandle(which); + if ((h == INVALID_HANDLE_VALUE) || (h == NULL)) { + h = DELAYED_CONSOLE_HANDLE; /* => open a console on demand */ + } return rktio_system_fd(rktio, - (intptr_t)GetStdHandle(which), + (intptr_t)h, mode | RKTIO_OPEN_NOT_DIR); #endif } @@ -272,7 +283,9 @@ int rktio_system_fd_is_terminal(rktio_t *rktio, intptr_t fd) return isatty(fd); #endif #ifdef RKTIO_SYSTEM_WINDOWS - if (GetFileType((HANDLE)fd) == FILE_TYPE_CHAR) { + if ((HANDLE)fd == DELAYED_CONSOLE_HANDLE) + return 1; /* delayed console */ + else if (GetFileType((HANDLE)fd) == FILE_TYPE_CHAR) { DWORD mode; if (GetConsoleMode((HANDLE)fd, &mode)) return 1; @@ -324,9 +337,13 @@ rktio_fd_t *rktio_dup(rktio_t *rktio, rktio_fd_t *rfd) HANDLE newhandle; BOOL rc; - rc = DuplicateHandle(GetCurrentProcess(), rfd->fd, - GetCurrentProcess(), &newhandle, - 0, FALSE, DUPLICATE_SAME_ACCESS); + if (rfd->fd == DELAYED_CONSOLE_HANDLE) { + newhandle = DELAYED_CONSOLE_HANDLE; + rc = TRUE; + } else + rc = DuplicateHandle(GetCurrentProcess(), rfd->fd, + GetCurrentProcess(), &newhandle, + 0, FALSE, DUPLICATE_SAME_ACCESS); if (rc == FALSE) { get_windows_error(); @@ -384,7 +401,7 @@ static rktio_ok_t do_close(rktio_t *rktio /* maybe NULL */, rktio_fd_t *rfd, int deinit_fd(rfd, 1); ok = 1; - if (!rfd->th && !rfd->oth) { + if (!rfd->th && !rfd->oth && (rfd->fd != DELAYED_CONSOLE_HANDLE)) { if (!CloseHandle(rfd->fd)) { ok = 0; if (set_error) @@ -612,6 +629,8 @@ int poll_write_ready_or_flushed(rktio_t *rktio, rktio_fd_t *rfd, int check_flush } #endif #ifdef RKTIO_SYSTEM_WINDOWS + force_console(rfd); + if (rfd->modes & RKTIO_OPEN_SOCKET) { if (check_flushed) return RKTIO_POLL_READY; @@ -698,6 +717,8 @@ void rktio_poll_add(rktio_t *rktio, rktio_fd_t *rfd, rktio_poll_set_t *fds, int fds2 = RKTIO_GET_FDSET(fds, 2); RKTIO_FD_SET((intptr_t)rfd->sock, fds2); } else { + force_console(rfd); + if (modes & RKTIO_POLL_READ) { init_read_fd(rktio, rfd); if (rfd->th) { @@ -980,6 +1001,8 @@ static intptr_t adjust_input_text_for_pending_cr(rktio_fd_t *rfd, char *buffer, static void init_read_fd(rktio_t *rktio, rktio_fd_t *rfd) { + force_console(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. @@ -1243,6 +1266,8 @@ intptr_t rktio_write(rktio_t *rktio, rktio_fd_t *rfd, const char *buffer, intptr if (rfd->modes & RKTIO_OPEN_SOCKET) return rktio_socket_write(rktio, rfd, buffer, len); + force_console(rfd); + if (rktio_fd_is_regular_file(rktio, rfd) || rktio_fd_is_terminal(rktio, rfd)) { /* Regular files never block, so this code looks like the Unix @@ -1832,3 +1857,29 @@ static void WindowsFDOCleanup(Win_FD_Output_Thread *oth, int close_mode) } #endif + +/*========================================================================*/ +/* console */ +/*========================================================================*/ + +#ifdef RKTIO_SYSTEM_WINDOWS + +static void force_console(rktio_fd_t *rfd) { + /* DELAYED_CONSOLE_HANDLE is used to indicate that a console should be created on demand */ + if (rfd->fd == DELAYED_CONSOLE_HANDLE) { + HANDLE h; + int which; + + rktio_create_console(); + + if (rfd->modes & RKTIO_OPEN_READ) + which = STD_INPUT_HANDLE; + else + which = STD_OUTPUT_HANDLE; + h = GetStdHandle(which); + + rfd->fd = h; + } +} + +#endif diff --git a/racket/src/rktio/rktio_private.h b/racket/src/rktio/rktio_private.h index 1a1a742799..d3d9578e62 100644 --- a/racket/src/rktio/rktio_private.h +++ b/racket/src/rktio/rktio_private.h @@ -376,3 +376,7 @@ void rktio_forget_os_signal_handler(rktio_t *rktio); int rktio_system_time_is_dst(SYSTEMTIME *st, TIME_ZONE_INFORMATION *_tz); #endif +#ifdef RKTIO_SYSTEM_WINDOWS +void rktio_console_ctl_c(void); +void rktio_set_console_handler(void); +#endif diff --git a/racket/src/rktio/rktio_signal.c b/racket/src/rktio/rktio_signal.c index f2a9cdeae4..caf143f6c2 100644 --- a/racket/src/rktio/rktio_signal.c +++ b/racket/src/rktio/rktio_signal.c @@ -26,9 +26,15 @@ static void signal_received(int i) #if defined(RKTIO_SYSTEM_WINDOWS) static BOOL WINAPI ConsoleBreakHandler(DWORD op) { + rktio_console_ctl_c(); signal_received(RKTIO_OS_SIGNAL_INT); return TRUE; } + +void rktio_set_console_handler(void) +{ + SetConsoleCtrlHandler(ConsoleBreakHandler, TRUE); +} #endif #if defined(RKTIO_SYSTEM_UNIX) @@ -66,7 +72,7 @@ void rktio_install_os_signal_handler(rktio_t *rktio) #endif #if defined(RKTIO_SYSTEM_WINDOWS) - SetConsoleCtrlHandler(ConsoleBreakHandler, TRUE); + rktio_set_console_handler(); #endif } diff --git a/racket/src/worksp/librktio/librktio.vcproj b/racket/src/worksp/librktio/librktio.vcproj index 40932cf181..b53562aeff 100644 --- a/racket/src/worksp/librktio/librktio.vcproj +++ b/racket/src/worksp/librktio/librktio.vcproj @@ -206,6 +206,10 @@ RelativePath="..\..\rktio\rktio_wide.c" > + + diff --git a/racket/src/worksp/librktio/librktio.vcxproj b/racket/src/worksp/librktio/librktio.vcxproj index 35e5e25eac..46ff016a5d 100644 --- a/racket/src/worksp/librktio/librktio.vcxproj +++ b/racket/src/worksp/librktio/librktio.vcxproj @@ -140,6 +140,7 @@ +