Skip to content

Commit 5377bd2

Browse files
HeikoKlareniraj-modi
authored andcommitted
Fix "no more handles" exception during Edge browser creation #339
The Edge browser creation uses Display.readAndDispath() to process the OS events for browser instantiation. When there are other asynchronous executions scheduled while the browser is being initialized, they may be processed in between the processing of browser-instantiating OS events if too much time elapses between them. In case such an asynchronous execution changes a state that makes the browser instantiation fail, such as disposing the composite parent of the browser, an exception occurs. In order to avoid the processing of asynchronous executions during browser instantiation, the change ensures that readAndDisplay() is only called when an OS event is present to be processed.
1 parent 0934f75 commit 5377bd2

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

bundles/org.eclipse.swt/Eclipse SWT Browser/win32/org/eclipse/swt/browser/Edge.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,8 @@ static int callAndWait(long[] ppv, ToIntFunction<IUnknown> callable) {
222222
ppv[0] = 0;
223223
phr[0] = callable.applyAsInt(completion);
224224
completion.Release();
225-
Display display = Display.getCurrent();
226225
while (phr[0] == COM.S_OK && ppv[0] == 0) {
227-
if (!display.readAndDispatch()) display.sleep();
226+
processNextOSMessage();
228227
}
229228
return phr[0];
230229
}
@@ -241,13 +240,33 @@ static int callAndWait(String[] pstr, ToIntFunction<IUnknown> callable) {
241240
pstr[0] = null;
242241
phr[0] = callable.applyAsInt(completion);
243242
completion.Release();
244-
Display display = Display.getCurrent();
245243
while (phr[0] == COM.S_OK && pstr[0] == null) {
246-
if (!display.readAndDispatch()) display.sleep();
244+
processNextOSMessage();
247245
}
248246
return phr[0];
249247
}
250248

249+
/**
250+
* Processes a single OS message using {@link Display#readAndDispatch()}. This
251+
* is required for processing the OS events during browser initialization, since
252+
* Edge browser initialization happens asynchronously.
253+
* <p>
254+
* {@link Display#readAndDisplay()} also processes events scheduled for
255+
* asynchronous execution via {@link Display#asyncExec(Runnable)}. This may
256+
* include events such as the disposal of the browser's parent composite, which
257+
* leads to a failure in browser initialization if processed in between the OS
258+
* events for initialization. Thus, this method does not implement an ordinary
259+
* readAndDispatch loop, but waits for an OS event to be processed.
260+
*/
261+
private static void processNextOSMessage() {
262+
Display display = Display.getCurrent();
263+
MSG msg = new MSG();
264+
while (!OS.PeekMessage (msg, 0, 0, 0, OS.PM_NOREMOVE)) {
265+
display.sleep();
266+
}
267+
display.readAndDispatch();
268+
}
269+
251270
static ICoreWebView2CookieManager getCookieManager() {
252271
if (Instances.isEmpty()) {
253272
SWT.error(SWT.ERROR_NOT_IMPLEMENTED, null, " [WebView2: cookie access requires a Browser instance]");

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_browser_Browser.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,17 @@ public void test_ConstructorLorg_eclipse_swt_widgets_CompositeI() {
268268
browser = createBrowser(null, SWT.NONE); // Should throw.
269269
}
270270

271+
/**
272+
* Regression test for issue #339: [Edge] No more handle exceptions from Edge browser
273+
*/
274+
@Test
275+
public void test_Constructor_asyncParentDisposal() {
276+
Display.getCurrent().asyncExec(() -> {
277+
shell.dispose();
278+
});
279+
Browser browser = createBrowser(shell, SWT.EDGE);
280+
assertFalse(browser.isDisposed());
281+
}
271282

272283
@Test
273284
public void test_evalute_Cookies () {

0 commit comments

Comments
 (0)