Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault when run from child thread. #26

Open
OtterCode opened this issue Jul 9, 2018 · 7 comments
Open

Segfault when run from child thread. #26

OtterCode opened this issue Jul 9, 2018 · 7 comments

Comments

@OtterCode
Copy link

Hello! Thank you for building this, first of all! I've had alright success running this from the main thread, but it seems to die when run from a child. Here's the segfault:

1   0x7fdcc656c247 /usr/lib/x86_64-linux-gnu/libjavascriptcoregtk-4.0.so.18(WTFCrash+0x17) [0x7fdcc656c247]
2   0x7fdcc7ced999 /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37(+0x67d999) [0x7fdcc7ced999]
3   0x7fdcc7d31d9a /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37(+0x6c1d9a) [0x7fdcc7d31d9a]
4   0x7fdcc7d32219 /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37(+0x6c2219) [0x7fdcc7d32219]
5   0x7fdcc7faf0d0 /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37(+0x93f0d0) [0x7fdcc7faf0d0]
6   0x7fdcc6833e72 /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0(g_object_unref+0x1a2) [0x7fdcc6833e72]
7   0x7fdcc48f0041 /lib/x86_64-linux-gnu/libc.so.6(+0x43041) [0x7fdcc48f0041]
8   0x7fdcc48f013a /lib/x86_64-linux-gnu/libc.so.6(+0x4313a) [0x7fdcc48f013a]
9   0x7fdcc48ceb9e /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xee) [0x7fdcc48ceb9e]
10  0x55777992389a target/debug/rust_ksl_uploader(+0x889a) [0x55777992389a]
Segmentation fault (core dumped)

And here's the minimal code to reproduce:

extern crate web_view;

use web_view::*;
use std::thread::spawn;

const INDEX: &str = r#"<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    This is a test.
  </body>
</html>
"#;

fn main() {
    let size = (800, 800);
    let resizable = true;
    let debug = true;
    let init_cb = |_webview| {};
    let frontend_cb = |_webview: &mut _, _arg: &_, _userdata: &mut _| {};
    let userdata = ();
    let view = spawn(move || {
        run("test thread", Content::Html(INDEX), Some(size), resizable, debug, init_cb, frontend_cb, userdata);
    });

    view.join().expect("Join Error");
}
@OtterCode
Copy link
Author

The fault only occurs when the window is closed, either via the quit menu, or by closing the window. The system is Ubuntu 18.

@OtterCode
Copy link
Author

Interesting. I added a sleep after the join, followed by a print. The "Join Error" expect does not get triggered, and the window doesn't close until main is complete, at which point the segfault gets dumped.

@richardhozak
Copy link
Collaborator

richardhozak commented Nov 10, 2018

Hello, could you check if this problem persists after #36 was merged? I am not able to reproduce this bug. Here is your minimal example code rewritten to use the new api of web-view crate:

extern crate web_view;

use web_view::*;
use std::thread::spawn;

const INDEX: &str = r#"<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    This is a test.
  </body>
</html>
"#;

fn main() {
    let callback = |_view: &mut WebView<()>, _arg: &str| Ok(());
    let view = spawn(move || {
        WebViewBuilder::new()
            .title("test thread")
            .content(Content::Html(INDEX))
            .size(800, 600)
            .resizable(true)
            .debug(true)
            .user_data(())
            .invoke_handler(callback)
            .build()
            .expect("Build Error")
            .run()
            .expect("Run Error");
    });

    view.join().expect("Join Error");
}

@jrop
Copy link

jrop commented Jan 29, 2019

I got a core dump as well, but I have the WebView running in the main thread:

fn main() {
  std::thread::spawn(move || {
    //... set up file watchers using `notify`
  });

  let wv = MyController::web_view();
  wv.run().unwrap();
}

@jrop
Copy link

jrop commented Jan 29, 2019

And here's the coredump stack frame:

#0  0x00007f63e6322077 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007f63e6303535 in __GI_abort () at abort.c:79
#2  0x00007f63e636a516 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7f63e648ec00 "%s\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007f63e63713aa in malloc_printerr (str=str@entry=0x7f63e6490490 "malloc_consolidate(): invalid chunk size") at malloc.c:5336
#4  0x00007f63e6371695 in malloc_consolidate (av=av@entry=0x7f63e64c5c40 <main_arena>) at malloc.c:4427
#5  0x00007f63e637358c in _int_free (av=0x7f63e64c5c40 <main_arena>, p=0x55c3e29d8020, have_lock=<optimized out>) at malloc.c:4348
#6  0x00007f63c56f2d32 in  () at /usr/lib/x86_64-linux-gnu/dri/nouveau_dri.so
#7  0x00007f63c58d51e9 in  () at /usr/lib/x86_64-linux-gnu/dri/nouveau_dri.so
#8  0x00007f63c58d40d3 in  () at /usr/lib/x86_64-linux-gnu/dri/nouveau_dri.so
#9  0x00007f63dc07c5b9 in  () at /usr/lib/x86_64-linux-gnu/libEGL_mesa.so.0
#10 0x00007f63dc072c75 in eglDestroyContext () at /usr/lib/x86_64-linux-gnu/libEGL_mesa.so.0
#11 0x00007f63e97de511 in  () at /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37
#12 0x00007f63e97de579 in  () at /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37
#13 0x00007f63e9e6fa8b in  () at /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37
#14 0x00007f63e9e6fd3b in  () at /usr/lib/x86_64-linux-gnu/libwebkit2gtk-4.0.so.37
#15 0x00007f63e632542c in __run_exit_handlers (status=0, listp=0x7f63e64c5718 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:108
#16 0x00007f63e632555a in __GI_exit (status=<optimized out>) at exit.c:139
#17 0x00007f63e63050a2 in __libc_start_main (main=0x55c3e1195e80 <main>, argc=1, argv=0x7fff37298bc8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff37298bb8)
    at ../csu/libc-start.c:342
#18 0x000055c3e11853ba in _start ()

@quadrupleslap
Copy link
Collaborator

Note: You could never run this on a non-main thread on macOS anyway, because macOS is weird like that.

@Zennii
Copy link

Zennii commented Jun 25, 2019

I've come across this issue as well. Ubuntu 18.04 and libwebkit2gtk-4.0 package is installed (If that's even necessary or useful). Here is the minimal code that consistently produces the issue for me with the current API (With sleep to show the window hangs):

use web_view::*;
use std::time::Duration;

fn main() {
    std::thread::spawn(|| {
        let mut wv = web_view::builder()
            .content(web_view::Content::Url(""))
            .user_data(0)
            .invoke_handler(|wv, arg| {
                // terminate in here causes free(): invalid pointer
                Ok(())
            })
            .build().expect("Build Error");
        wv.run().expect("Run Error");
    });
    std::thread::sleep(Duration::from_secs(7));
}

I did some of my own snooping around by running it through valgrind and found that when I placed mem::forget(_lock); near the bottom of the _into_inner(&mut self) function in a local copy of the crate, a ton of errors reported by valgrind go away during the drop and malloc_consolidate(): invalid chunk size stops happening and thus the program doesn't crash, but the window will hang until the main thread is done and the entire program still closes with signal 6 SIGABRT when it's done. You can circumvent the hanging by waiting an indeterminate amount of time after the window thinks it's dead and returns None to step a few times, like this:

std::thread::spawn(|| {
    let mut wv = web_view::builder()
        .content(web_view::Content::Url(""))
        .user_data(0)
        .invoke_handler(|wv, arg| {Ok(())})
        .build().unwrap();
    let mut looped = 0;
    loop {
        match wv.step() {
            Some(Ok(a)) => (),
            Some(Err(e)) => (),
            None => {
                looped += 1;
                if looped > 4 {
                    println!("Closed");
                    return;
                }
            }
        }
    }
});

but it's a very ugly magical workaround and I'm really unsure as to why it works exactly. It feels like some kind of race condition, but I'm not sure how the window manager works. Hope this helps deduce what's wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants