Windows: move on-demand console to rktio

In GUI-application mode (e.g., running GRacket), a console is allocated
on demand if a program tries to use the original ports. Move that
on-demand handling into rktio, where it's simpler and works for
RacketCS.
This commit is contained in:
Matthew Flatt 2018-11-10 18:47:06 -08:00
parent 982942b258
commit 67b721e5b7
13 changed files with 209 additions and 335 deletions

View File

@ -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);
}

View File

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

View File

@ -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);

View File

@ -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, ...)
{

View File

@ -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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -206,6 +206,10 @@
RelativePath="..\..\rktio\rktio_wide.c"
>
</File>
<File
RelativePath="..\..\rktio\rktio_console.c"
>
</File>
<File
RelativePath="..\..\rktio\rktio_main.c"
>

View File

@ -140,6 +140,7 @@
<ClCompile Include="..\..\rktio\rktio_error.c" />
<ClCompile Include="..\..\rktio\rktio_hash.c" />
<ClCompile Include="..\..\rktio\rktio_wide.c" />
<ClCompile Include="..\..\rktio\rktio_console.c" />
<ClCompile Include="..\..\rktio\rktio_main.c" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />