Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeo Ufimtsev2018-01-30 16:58:12 -0500
committerLeo Ufimtsev2018-01-30 17:01:20 -0500
commit5ccd99b1763a271291710a2a3ed1df3894c149a6 (patch)
tree776ba16a8f8d31ff4882766c8787ed4744af356e
parent9699273a0dd1d1b553030ea14d565c8fb142c1d0 (diff)
downloadeclipse.platform.swt-5ccd99b1763a271291710a2a3ed1df3894c149a6.tar.gz
eclipse.platform.swt-5ccd99b1763a271291710a2a3ed1df3894c149a6.tar.xz
eclipse.platform.swt-5ccd99b1763a271291710a2a3ed1df3894c149a6.zip
Bug 529870 – [webkit2]BrowserProblemI20180130-2000
Fixing a corner case that can generate a deadlock. - A) User calls evaluate(SCRIPT) - B) The SCRIPT calls a BrowserFunction, (java/swt) - C) The BrowserFunction calls evaluate() Now webkit_web_view_run_javascript() in C never starts because webkit is still executing A. But A never finishes because it's waiting for C to complete to get a return value for A's callback. Solution: Don't allow blocking evaluation in BrowserFunction() callbacks. This shouldn't affect folks mostly, because from what I gather people use 'evaluate' as a form of execute(). This has gone unnoticed on Win32/Cocoa because issue isn't explicitly raised and 'evaluate()' return value wasn't used. Verified with AllBrowser JUnits. Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=5298702 Change-Id: Iddc8c753051455f6706ea81db85e0c6610be11a9 Signed-off-by: Leo Ufimtsev <lufimtse@redhat.com>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java22
-rw-r--r--tests/org.eclipse.swt.tests.gtk/Bug Snippets/org/eclipse/swt/tests/gtk/snippets/Bug518961_RTTest.java51
2 files changed, 67 insertions, 6 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java
index 7c6a777ff5..6b810715fb 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java
@@ -533,7 +533,6 @@ class WebKit extends WebBrowser {
static Object webkit2callJavaCallback(Object [] cb_args) {
assert cb_args.length == 4;
Object returnValue = null;
-
Long webViewLocal = (Double.valueOf((String) cb_args[0])).longValue();
Browser browser = FindBrowser((long /*int*/) webViewLocal.longValue());
Integer functionIndex = ((Double) cb_args[1]).intValue();
@@ -550,6 +549,7 @@ class WebKit extends WebBrowser {
}
try {
// Call user code. Exceptions can occur.
+ nonBlockingEvaluate++;
Object [] user_args = (Object []) cb_args[3];
returnValue = function.function(user_args);
} catch (Exception e ) {
@@ -558,6 +558,8 @@ class WebKit extends WebBrowser {
// webkit2 doesn't, so we don't have 'if (function.isEvaluate)' logic here.
System.err.println("SWT Webkit: Exception occured in user code of function: " + function.name);
returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ());
+ } finally {
+ nonBlockingEvaluate--;
}
return returnValue;
}
@@ -1598,8 +1600,11 @@ private static class Webkit2AsyncToSync {
} else {
// Callback logic: Initiate an async callback and wait for it to finish.
// The callback comes back in runjavascript_callback(..) below.
- Consumer <Integer> asyncFunc = (callbackId) -> WebKitGTK.webkit_web_view_run_javascript(webView, Converter.wcsToMbcs(script, true), 0, runjavascript_callback.getAddress(), callbackId);
- Webkit2AsyncReturnObj retObj = execAsyncAndWaitForReturn(browser, asyncFunc);
+ Consumer <Integer> asyncFunc = (callbackId) -> {
+ WebKitGTK.webkit_web_view_run_javascript(webView, Converter.wcsToMbcs(script, true), 0, runjavascript_callback.getAddress(), callbackId);
+ };
+
+ Webkit2AsyncReturnObj retObj = execAsyncAndWaitForReturn(browser, asyncFunc, " The following javascript was executed:\n" + script +"\n\n");
if (retObj.swtAsyncTimeout) {
return null;
@@ -1656,7 +1661,7 @@ private static class Webkit2AsyncToSync {
}
Consumer<Integer> asyncFunc = (callbackId) -> WebKitGTK.webkit_web_resource_get_data(WebKitWebResource, 0, getText_callback.getAddress(), callbackId);
- Webkit2AsyncReturnObj retObj = execAsyncAndWaitForReturn(browser, asyncFunc);
+ Webkit2AsyncReturnObj retObj = execAsyncAndWaitForReturn(browser, asyncFunc, " getText() was called");
if (retObj.swtAsyncTimeout)
return "SWT WEBKIT TIMEOUT ERROR";
@@ -1690,7 +1695,7 @@ private static class Webkit2AsyncToSync {
/**
* You should check 'retObj.swtAsyncTimeout' after making a call to this.
*/
- private static Webkit2AsyncReturnObj execAsyncAndWaitForReturn(Browser browser, Consumer<Integer> asyncFunc) {
+ private static Webkit2AsyncReturnObj execAsyncAndWaitForReturn(Browser browser, Consumer<Integer> asyncFunc, String additionalErrorInfo) {
Webkit2AsyncReturnObj retObj = new Webkit2AsyncReturnObj();
int callbackId = CallBackMap.putObject(retObj);
asyncFunc.accept(callbackId);
@@ -1717,7 +1722,9 @@ private static class Webkit2AsyncToSync {
+ "2) Deadlock in swt/webkit2 logic. This is probably a bug in SWT.\n"
+ reportErrMsg + "\n"
+ "For bug report, please atatch this stack trace:\n"
- + stackTrace);
+ + stackTrace
+ + "\n Additional information about the error is as following:\n"
+ + additionalErrorInfo);
retObj.swtAsyncTimeout = true;
break;
}
@@ -1731,6 +1738,9 @@ private static class Webkit2AsyncToSync {
@Override
public Object evaluate (String script) throws SWTException {
+ if ("".equals(script)) {
+ return null; // A litte optimization. Sometimes evaluate() is called with a generated script, where the generated script is sometimes empty.
+ }
if (WEBKIT2){
if (!isJavascriptEnabled()) {
return null;
diff --git a/tests/org.eclipse.swt.tests.gtk/Bug Snippets/org/eclipse/swt/tests/gtk/snippets/Bug518961_RTTest.java b/tests/org.eclipse.swt.tests.gtk/Bug Snippets/org/eclipse/swt/tests/gtk/snippets/Bug518961_RTTest.java
new file mode 100644
index 0000000000..9cdbf670d6
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/Bug Snippets/org/eclipse/swt/tests/gtk/snippets/Bug518961_RTTest.java
@@ -0,0 +1,51 @@
+package org.eclipse.swt.tests.gtk.snippets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+
+/**
+ *
+ To get this guy to work,
+ 1) Uncomment line with "UNCOMMENT THIS".
+ 2) Get hold of nebula rich text project. (found inside org.eclipse.nebula)
+ edit .classpath and add:
+ <classpathentry kind="src" path="/org.eclipse.nebula.widgets.richtext"/>
+ (This can be done via auto fix.
+
+ Before Fix: When running, error messages thrown into console.
+ After fix: Snippet runs as expected.
+ */
+public class Bug518961_RTTest extends org.eclipse.swt.widgets.Shell {
+
+ public Bug518961_RTTest(Display display) {
+ super(display, SWT.SHELL_TRIM);
+ createContents();
+ }
+
+ private void createContents() {
+// new RichTextEditor(this); /// UNCOMMENT THIS.
+ }
+
+ public static void main(String[] args) {
+ Display display = new Display();
+ Shell shell = new Bug518961_RTTest(display);
+ shell.setSize(800, 800);
+ shell.setLayout(new FillLayout());
+
+ shell.pack();
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ display.dispose();
+ }
+
+ @Override
+ protected void checkSubclass() {
+ }
+
+} \ No newline at end of file

Back to the top