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 @@
+