summaryrefslogtreecommitdiff
path: root/native/runner/runnerw/runnerw.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'native/runner/runnerw/runnerw.cpp')
-rw-r--r--native/runner/runnerw/runnerw.cpp80
1 files changed, 66 insertions, 14 deletions
diff --git a/native/runner/runnerw/runnerw.cpp b/native/runner/runnerw/runnerw.cpp
index 8936b28f53e8..03e975ef81a1 100644
--- a/native/runner/runnerw/runnerw.cpp
+++ b/native/runner/runnerw/runnerw.cpp
@@ -18,16 +18,25 @@ void PrintUsage() {
exit(0);
}
-void ErrorMessage(char *str) {
-
+void ErrorMessage(char *operationName) {
LPVOID msg;
-
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &msg, 0, NULL);
-
- printf("%s: %s\n", str, msg);
- LocalFree(msg);
+ DWORD lastError = GetLastError();
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ lastError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&msg,
+ 0,
+ NULL);
+ if (msg) {
+ fprintf(stderr, "%s failed with error %d: %s\n", operationName, lastError, msg);
+ LocalFree(msg);
+ }
+ else {
+ fprintf(stderr, "%s failed with error %d (no message available)\n", operationName, lastError);
+ }
+ fflush(stderr);
}
void CtrlBreak() {
@@ -126,6 +135,33 @@ bool hasEnding(std::string const &fullString, std::string const &ending) {
}
}
+BOOL attachChildConsole(PROCESS_INFORMATION const &childProcessInfo) {
+ if (!FreeConsole()) {
+ ErrorMessage("FreeConsole");
+ return FALSE;
+ }
+ int attempts = 20;
+ for (int i = 0; i < attempts; i++) {
+ DWORD sleepMillis = i < 5 ? 30 : (i < 10 ? 100 : 500);
+ // sleep to let child process initialize itself
+ Sleep(sleepMillis);
+ if (WaitForSingleObject(childProcessInfo.hProcess, 0) != WAIT_TIMEOUT) {
+ // child process has been terminated, no console to attach to
+ return FALSE;
+ }
+ if (AttachConsole(childProcessInfo.dwProcessId)) {
+ return TRUE;
+ }
+ // ERROR_GEN_FAILURE means "the specified process does not exist"
+ // Seems it also means that the console hasn't been fully initialized.
+ if (GetLastError() != ERROR_GEN_FAILURE) {
+ break;
+ }
+ }
+ ErrorMessage("AttachConsole");
+ return FALSE;
+}
+
int main(int argc, char * argv[]) {
if (argc < 2) {
PrintUsage();
@@ -195,18 +231,34 @@ int main(int argc, char * argv[]) {
char* c_args = new char[args.size() + 1];
strcpy(c_args, args.c_str());
- if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
- ErrorMessage("SetConsoleCtrlHandler");
+ DWORD processFlag = CREATE_DEFAULT_ERROR_MODE;
+ BOOL hasConsoleWindow = GetConsoleWindow() != NULL;
+ if (hasConsoleWindow) {
+ processFlag |= CREATE_NO_WINDOW;
}
- if (!CreateProcess(c_app, // Application name
- c_args, // Application arguments
- NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE, NULL, NULL, &si, &pi)) {
+ if (!CreateProcess(
+ c_app,
+ c_args,
+ NULL,
+ NULL,
+ TRUE,
+ processFlag,
+ NULL,
+ NULL,
+ &si,
+ &pi)) {
ErrorMessage("CreateProcess");
CloseHandle(newstdin);
CloseHandle(write_stdin);
exit(0);
}
+ if (hasConsoleWindow) {
+ attachChildConsole(pi);
+ }
+ if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE)) {
+ ErrorMessage("SetConsoleCtrlHandler");
+ }
CreateThread(NULL, 0, &scanStdinThread, &write_stdin, 0, NULL);