Skip to content

Commit 6d9c144

Browse files
committed
Open Windows standard file descriptors before initializing Ruby
1 parent f52f09d commit 6d9c144

File tree

5 files changed

+88
-59
lines changed

5 files changed

+88
-59
lines changed

binding/binding-mri-win32.h

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#ifndef BINDING_MRI_WIN32_H
2+
#define BINDING_MRI_WIN32_H
3+
4+
#include <windows.h>
5+
#include "util/win-consoleutils.h"
6+
7+
// Attempts to set $stdout and $stdin accordingly on Windows. Only
8+
// called when debug mode is on, since that's when the console
9+
// should be active.
10+
void configureWindowsStreams() {
11+
const int stdoutFD = getStdFD(STD_OUTPUT_HANDLE);
12+
13+
// Configure $stdout
14+
if (stdoutFD >= 0) {
15+
VALUE winStdout = rb_funcall(rb_cIO, rb_intern("new"), 2,
16+
INT2NUM(stdoutFD), rb_str_new_cstr("w+"));
17+
18+
rb_gv_set("stdout", winStdout);
19+
}
20+
21+
const int stdinFD = getStdFD(STD_INPUT_HANDLE);
22+
23+
// Configure $stdin
24+
if (stdinFD >= 0) {
25+
VALUE winStdin = rb_funcall(rb_cIO, rb_intern("new"), 2,
26+
INT2NUM(stdinFD), rb_str_new_cstr("r"));
27+
28+
rb_gv_set("stdin", winStdin);
29+
}
30+
31+
const int stderrFD = getStdFD(STD_ERROR_HANDLE);
32+
33+
// Configure $stderr
34+
if (stderrFD >= 0) {
35+
VALUE winStderr = rb_funcall(rb_cIO, rb_intern("new"), 2,
36+
INT2NUM(stderrFD), rb_str_new_cstr("w+"));
37+
38+
rb_gv_set("stderr", winStderr);
39+
}
40+
}
41+
42+
#endif

binding/binding-mri.cpp

+1-55
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ extern "C" {
5050
}
5151

5252
#ifdef __WIN32__
53-
#include <fcntl.h>
54-
#include "util/win-consoleutils.h"
53+
#include "binding-mri-win32.h"
5554
#endif
5655

5756
#include <assert.h>
@@ -72,9 +71,6 @@ extern const char module_rpg3[];
7271
static void mriBindingExecute();
7372
static void mriBindingTerminate();
7473
static void mriBindingReset();
75-
#ifdef __WIN32__
76-
static void configureWindowsStreams();
77-
#endif
7874

7975
ScriptBinding scriptBindingImpl = {mriBindingExecute, mriBindingTerminate,
8076
mriBindingReset};
@@ -274,10 +270,7 @@ static void mriBindingInit() {
274270
// Set $stdout and its ilk accordingly on Windows
275271
#ifdef __WIN32__
276272
if (shState->config().editor.debug)
277-
{
278-
reopenWindowsStreams();
279273
configureWindowsStreams();
280-
}
281274
#endif
282275

283276
// Load zlib, if it's present. Requires --with-static-linked-ext or zlib.so.
@@ -947,53 +940,6 @@ static void runRMXPScripts(BacktraceData &btData) {
947940
}
948941
}
949942

950-
// Attempts to set $stdout and $stdin accordingly on Windows. Only
951-
// called when debug mode is on, since that's when the console
952-
// should be active.
953-
#ifdef __WIN32__
954-
static void configureWindowsStreams() {
955-
#define HANDLE_VALID(handle) handle && handle != INVALID_HANDLE_VALUE
956-
957-
const HANDLE outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
958-
959-
// Configure $stdout
960-
if (HANDLE_VALID(outputHandle)) {
961-
const int stdoutFD = _open_osfhandle((intptr_t)outputHandle, _O_TEXT);
962-
963-
VALUE winStdout = rb_funcall(rb_cIO, rb_intern("new"), 2,
964-
INT2NUM(stdoutFD), rb_str_new_cstr("w+"));
965-
966-
rb_gv_set("stdout", winStdout);
967-
}
968-
969-
const HANDLE inputHandle = GetStdHandle(STD_INPUT_HANDLE);
970-
971-
// Configure $stdin
972-
if (HANDLE_VALID(inputHandle)) {
973-
const int stdinFD = _open_osfhandle((intptr_t)inputHandle, _O_TEXT);
974-
975-
VALUE winStdin = rb_funcall(rb_cIO, rb_intern("new"), 2,
976-
INT2NUM(stdinFD), rb_str_new_cstr("r"));
977-
978-
rb_gv_set("stdin", winStdin);
979-
}
980-
981-
const HANDLE errorHandle = GetStdHandle(STD_ERROR_HANDLE);
982-
983-
// Configure $stderr
984-
if (HANDLE_VALID(errorHandle)) {
985-
const int stderrFD = _open_osfhandle((intptr_t)errorHandle, _O_TEXT);
986-
987-
VALUE winStderr = rb_funcall(rb_cIO, rb_intern("new"), 2,
988-
INT2NUM(stderrFD), rb_str_new_cstr("w+"));
989-
990-
rb_gv_set("stderr", winStderr);
991-
}
992-
993-
#undef HANDLE_VALID
994-
}
995-
#endif // #ifdef __WIN32__
996-
997943
static void showExc(VALUE exc, const BacktraceData &btData) {
998944
VALUE bt = rb_funcall2(exc, rb_intern("backtrace"), 0, NULL);
999945
VALUE msg = rb_funcall2(exc, rb_intern("message"), 0, NULL);

src/main.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,9 @@ int main(int argc, char *argv[]) {
296296

297297
// Create a debug console in debug mode
298298
if (conf.editor.debug) {
299-
if (!setupWindowsConsole()) {
299+
if (setupWindowsConsole()) {
300+
reopenWindowsStreams();
301+
} else {
300302
char buf[200];
301303
snprintf(buf, sizeof(buf), "Error allocating console: %lu",
302304
GetLastError());

src/util/win-consoleutils.cpp

+38-3
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@ bool setupWindowsConsole()
1313
return (handle != NULL && handle != INVALID_HANDLE_VALUE);
1414
}
1515

16-
FILE *outStream;
17-
FILE *inStream;
18-
FILE *errStream;
16+
static FILE *outStream;
17+
static FILE *inStream;
18+
static FILE *errStream;
19+
20+
static int stdoutFD = -1;
21+
static int stderrFD = -1;
22+
static int stdinFD = -1;
23+
24+
static int openStdHandle(const DWORD &nStdHandle);
1925

2026
// Reopens the file streams. This should be done after successfully
2127
// setting up the console.
@@ -28,4 +34,33 @@ void reopenWindowsStreams()
2834
std::clog.clear();
2935
std::cerr.clear();
3036
std::cin.clear();
37+
38+
stdoutFD = openStdHandle(STD_OUTPUT_HANDLE);
39+
stdinFD = openStdHandle(STD_INPUT_HANDLE);
40+
stderrFD = openStdHandle(STD_ERROR_HANDLE);
41+
}
42+
43+
int getStdFD(const DWORD &nStdHandle)
44+
{
45+
switch (nStdHandle)
46+
{
47+
case STD_OUTPUT_HANDLE:
48+
return stdoutFD;
49+
case STD_INPUT_HANDLE:
50+
return stdinFD;
51+
case STD_ERROR_HANDLE:
52+
return stderrFD;
53+
default:
54+
return -1;
55+
}
56+
}
57+
58+
static int openStdHandle(const DWORD &nStdHandle)
59+
{
60+
const HANDLE handle = GetStdHandle(nStdHandle);
61+
62+
if (!handle || handle == INVALID_HANDLE_VALUE)
63+
return -1;
64+
65+
return _open_osfhandle((intptr_t)handle, _O_TEXT);
3166
}

src/util/win-consoleutils.h

+4
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33

44
#include <iostream>
55
#include <windows.h>
6+
#include <fcntl.h>
7+
#include <io.h>
68

79
bool setupWindowsConsole();
810

911
void reopenWindowsStreams();
1012

13+
int getStdFD(const DWORD &nStdHandle);
14+
1115
#endif

0 commit comments

Comments
 (0)