|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4 | 4 | *
|
5 | 5 | * This code is free software; you can redistribute it and/or modify it
|
@@ -134,6 +134,82 @@ tstring getJvmLibPath(const Jvm& jvm) {
|
134 | 134 | }
|
135 | 135 |
|
136 | 136 |
|
| 137 | +class RunExecutorWithMsgLoop { |
| 138 | +public: |
| 139 | + static DWORD apply(const Executor& exec) { |
| 140 | + RunExecutorWithMsgLoop instance(exec); |
| 141 | + |
| 142 | + UniqueHandle threadHandle = UniqueHandle(CreateThread(NULL, 0, worker, |
| 143 | + static_cast<LPVOID>(&instance), 0, NULL)); |
| 144 | + if (threadHandle.get() == NULL) { |
| 145 | + JP_THROW(SysError("CreateThread() failed", CreateThread)); |
| 146 | + } |
| 147 | + |
| 148 | + MSG msg; |
| 149 | + BOOL bRet; |
| 150 | + while((bRet = GetMessage(&msg, instance.hwnd, 0, 0 )) != 0) { |
| 151 | + if (bRet == -1) { |
| 152 | + JP_THROW(SysError("GetMessage() failed", GetMessage)); |
| 153 | + } else { |
| 154 | + TranslateMessage(&msg); |
| 155 | + DispatchMessage(&msg); |
| 156 | + } |
| 157 | + } |
| 158 | + |
| 159 | + // Wait for worker thread to terminate to guarantee it will not linger |
| 160 | + // around after the thread running a message loop terminates. |
| 161 | + const DWORD res = ::WaitForSingleObject(threadHandle.get(), INFINITE); |
| 162 | + if (WAIT_FAILED == res) { |
| 163 | + JP_THROW(SysError("WaitForSingleObject() failed", |
| 164 | + WaitForSingleObject)); |
| 165 | + } |
| 166 | + |
| 167 | + LOG_TRACE(tstrings::any() |
| 168 | + << "Executor worker thread terminated. Exit code=" |
| 169 | + << instance.exitCode); |
| 170 | + return instance.exitCode; |
| 171 | + } |
| 172 | + |
| 173 | +private: |
| 174 | + RunExecutorWithMsgLoop(const Executor& v): exec(v) { |
| 175 | + exitCode = 1; |
| 176 | + |
| 177 | + // Message-only window. |
| 178 | + hwnd = CreateWindowEx(0, _T("STATIC"), _T(""), 0, 0, 0, 0, 0, |
| 179 | + HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); |
| 180 | + if (!hwnd) { |
| 181 | + JP_THROW(SysError("CreateWindowEx() failed", CreateWindowEx)); |
| 182 | + } |
| 183 | + } |
| 184 | + |
| 185 | + static DWORD WINAPI worker(LPVOID param) { |
| 186 | + static_cast<RunExecutorWithMsgLoop*>(param)->run(); |
| 187 | + return 0; |
| 188 | + } |
| 189 | + |
| 190 | + void run() { |
| 191 | + JP_TRY; |
| 192 | + exitCode = static_cast<DWORD>(exec.execAndWaitForExit()); |
| 193 | + JP_CATCH_ALL; |
| 194 | + |
| 195 | + JP_TRY; |
| 196 | + if (!PostMessage(hwnd, WM_QUIT, 0, 0)) { |
| 197 | + JP_THROW(SysError("PostMessage(WM_QUIT) failed", PostMessage)); |
| 198 | + } |
| 199 | + return; |
| 200 | + JP_CATCH_ALL; |
| 201 | + |
| 202 | + // All went wrong, PostMessage() failed. Just terminate with error code. |
| 203 | + exit(1); |
| 204 | + } |
| 205 | + |
| 206 | +private: |
| 207 | + const Executor& exec; |
| 208 | + DWORD exitCode; |
| 209 | + HWND hwnd; |
| 210 | +}; |
| 211 | + |
| 212 | + |
137 | 213 | void launchApp() {
|
138 | 214 | // [RT-31061] otherwise UI can be left in back of other windows.
|
139 | 215 | ::AllowSetForegroundWindow(ASFW_ANY);
|
@@ -180,7 +256,7 @@ void launchApp() {
|
180 | 256 | exec.arg(arg);
|
181 | 257 | });
|
182 | 258 |
|
183 |
| - DWORD exitCode = static_cast<DWORD>(exec.execAndWaitForExit()); |
| 259 | + DWORD exitCode = RunExecutorWithMsgLoop::apply(exec); |
184 | 260 |
|
185 | 261 | exit(exitCode);
|
186 | 262 | return;
|
|
0 commit comments