Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changes/linux-request-queue-feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
wry: minor
---

Added `linux-request-queue` feature flag (enabled by default, which matches previous behavior).
The queue prevents an unknown concurrency bug with loading multiple URIs at the same time on webkit2gtk.
But it can introduce a deadlock situation under certain conditions (https://github.com/tauri-apps/tauri/issues/12589) and it prevents parallelization of request loading.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ exclude = ["/.changes", "/.github", "/audits", "/wry-logo.svg"]

[package.metadata.docs.rs]
no-default-features = true
features = ["drag-drop", "protocol", "os-webview"]
features = ["drag-drop", "protocol", "os-webview", "linux-request-queue"]
targets = [
"x86_64-unknown-linux-gnu",
"x86_64-pc-windows-msvc",
Expand All @@ -26,14 +26,15 @@ rustc-args = ["--cfg", "docsrs"]
rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["drag-drop", "protocol", "os-webview", "x11"]
default = ["drag-drop", "protocol", "os-webview", "x11", "linux-request-queue"]
serde = ["dpi/serde"]
drag-drop = []
protocol = []
devtools = []
transparent = []
fullscreen = []
linux-body = ["webkit2gtk/v2_40", "os-webview"]
linux-request-queue = []
mac-proxy = []
os-webview = [
"javascriptcore-rs",
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,10 @@ Wry uses a set of feature flags to toggle several advanced features.
libraries and prevent from building documentation on doc.rs fails.
- `linux-body`: Enables body support of custom protocol request on Linux. Requires
webkit2gtk v2.40 or above.
- `linux-request-queue` (default): Enables a request queue for webviews on Linux.
This Prevents an unknown concurrency bug with loading multiple URIs at the same time on webkit2gtk.
You might want to disable it because it can affect request performance, lead to a deadlock under certain conditions
and it might no longer be needed with newer WebKitGTK versions.
- `tracing`: enables [`tracing`] for `evaluate_script`, `ipc_handler` and `custom_protocols.

### Partners
Expand Down
9 changes: 7 additions & 2 deletions src/webkitgtk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,13 @@ impl InnerWebView {

// Navigation
if let Some(url) = attributes.url {
web_context.queue_load_uri(w.webview.clone(), url, attributes.headers);
web_context.flush_queue_loader();
#[cfg(feature = "linux-request-queue")]
{
web_context.queue_load_uri(w.webview.clone(), url, attributes.headers);
web_context.flush_queue_loader();
}
#[cfg(not(feature = "linux-request-queue"))]
web_context.load_uri(w.webview.clone(), url, attributes.headers);
} else if let Some(html) = attributes.html {
w.webview.load_html(&html, None);
}
Expand Down
32 changes: 32 additions & 0 deletions src/webkitgtk/web_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use webkit2gtk::{
#[derive(Debug)]
pub struct WebContextImpl {
context: WebContext,
#[cfg(feature = "linux-request-queue")]
webview_uri_loader: Rc<WebViewUriLoader>,
automation: bool,
app_info: Option<ApplicationInfo>,
Expand Down Expand Up @@ -83,6 +84,7 @@ impl WebContextImpl {
Self {
context,
automation,
#[cfg(feature = "linux-request-queue")]
webview_uri_loader: Rc::default(),
app_info: Some(app_info),
}
Expand Down Expand Up @@ -110,14 +112,20 @@ pub trait WebContextExt {
where
F: Fn(crate::WebViewId, Request<Vec<u8>>, RequestAsyncResponder) + 'static;

/// Directly loads a URI for a [`WebView`] bypassing the [`WebViewUriLoader`].
#[cfg(not(feature = "linux-request-queue"))]
fn load_uri(&self, webview: WebView, url: String, headers: Option<http::HeaderMap>);

/// Add a [`WebView`] to the queue waiting to be opened.
///
/// See the [`WebViewUriLoader`] for more information.
#[cfg(feature = "linux-request-queue")]
fn queue_load_uri(&self, webview: WebView, url: String, headers: Option<http::HeaderMap>);

/// Flush all queued [`WebView`]s waiting to load a uri.
///
/// See the [`WebViewUriLoader`] for more information.
#[cfg(feature = "linux-request-queue")]
fn flush_queue_loader(&self);

/// If the context allows automation.
Expand Down Expand Up @@ -275,10 +283,32 @@ impl WebContextExt for super::WebContext {
Ok(())
}

#[cfg(not(feature = "linux-request-queue"))]
fn load_uri(&self, webview: WebView, uri: String, headers: Option<http::HeaderMap>) {
if let Some(headers) = headers {
let req = URIRequest::builder().uri(&uri).build();

if let Some(ref mut req_headers) = req.http_headers() {
for (header, value) in headers.iter() {
req_headers.append(
header.to_string().as_str(),
value.to_str().unwrap_or_default(),
);
}
}

webview.load_request(&req);
} else {
webview.load_uri(&uri);
}
}

#[cfg(feature = "linux-request-queue")]
fn queue_load_uri(&self, webview: WebView, url: String, headers: Option<http::HeaderMap>) {
self.os.webview_uri_loader.push(webview, url, headers)
}

#[cfg(feature = "linux-request-queue")]
fn flush_queue_loader(&self) {
self.os.webview_uri_loader.clone().flush()
}
Expand Down Expand Up @@ -409,12 +439,14 @@ struct WebviewUriRequest {
/// FIXME: We think this may be an underlying concurrency bug in webkit2gtk as the usual ways of
/// fixing threading issues are not working. Ideally, the locks are not needed if we can understand
/// the true cause of the bug.
#[cfg(feature = "linux-request-queue")]
#[derive(Debug, Default)]
struct WebViewUriLoader {
lock: AtomicBool,
queue: Mutex<VecDeque<WebviewUriRequest>>,
}

#[cfg(feature = "linux-request-queue")]
impl WebViewUriLoader {
/// Check if the lock is in use.
fn is_locked(&self) -> bool {
Expand Down