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

Segmentation fault at exit #12653

Open
rracariu opened this issue Nov 4, 2021 · 9 comments
Open

Segmentation fault at exit #12653

rracariu opened this issue Nov 4, 2021 · 9 comments
Assignees
Labels
bug Something isn't working correctly FFI Related to Foreign Function Interface APIs

Comments

@rracariu
Copy link

rracariu commented Nov 4, 2021

Project running under Deno 1.15.3 on Linux x64 will segfault at exit.

The stack trace is:

#0  0x00007ffff0f8e210 in ?? ()
#1  0x00007ffff7596408 in __nptl_deallocate_tsd () at pthread_create.c:300
#2  0x00007ffff759781b in __nptl_deallocate_tsd () at ../sysdeps/nptl/futex-internal.h:200
#3  start_thread (arg=0x7ffff15f5700) at pthread_create.c:473
#4  0x00007ffff6f2271f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95

Thread list

(gdb) info threads
  Id   Target Id         Frame
  1    Thread 0x7ffff7fdeb40 (LWP 20620) "deno" 0x00007ffff7598d2d in __GI___pthread_timedjoin_ex (threadid=140737242945280, thread_return=0x0, abstime=0x0, block=<optimized out>) at pthread_join_common.c:89
  2    Thread 0x7ffff6e00700 (LWP 20621) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
  3    Thread 0x7ffff65ff700 (LWP 20622) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
  4    Thread 0x7ffff5dfe700 (LWP 20623) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
  5    Thread 0x7ffff55fd700 (LWP 20624) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
  6    Thread 0x7ffff4dfc700 (LWP 20625) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
  7    Thread 0x7ffff45fb700 (LWP 20626) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
  8    Thread 0x7ffff3dfa700 (LWP 20627) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
  9    Thread 0x7ffff35f9700 (LWP 20628) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
  10   Thread 0x7ffff2df8700 (LWP 20629) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
  11   Thread 0x7ffff25f7700 (LWP 20630) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
  12   Thread 0x7ffff1df6700 (LWP 20631) "V8 DefaultWorke" 0x00007ffff759dad3 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x555558ff117c) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
* 13   Thread 0x7ffff15f5700 (LWP 20632) "tokio-runtime-w" 0x00007ffff0f8e210 in ?? ()
  14   Thread 0x7ffff0e0f700 (LWP 20633) "tokio-runtime-w" 0x00007ffff0f8e210 in ?? ()

Project is using non-blocking FFI

@lucacasonato lucacasonato added bug Something isn't working correctly FFI Related to Foreign Function Interface APIs labels Nov 7, 2021
@lucacasonato
Copy link
Member

We will need a reproduction to be able to fix this. Please provide the JS file + the code we can use to compile an lib to use for FFI.

@lucacasonato lucacasonato added the needs info needs further information to be properly triaged label Nov 7, 2021
@rracariu
Copy link
Author

rracariu commented Nov 9, 2021

JS test case:

const dylib = Deno.dlopen('libCrash.so', {
  "call_non_blocking": { parameters: ["buffer", "usize", "buffer", "usize"], result: "u32", nonblocking: true },
});

// cleanup on exit
globalThis.addEventListener('unload', async () => {
  try {
    // Without this line, it does not segfault
    await invoke_ffi();
    dylib.close()
  } catch (e) {
    console.log(e)
  }
  console.log('terminated.')
})

async function invoke_ffi() {
  const args = new Uint8Array(1);
  args[0] = "A".charCodeAt(0)

  const res = new Uint8Array(1);

  const status = await dylib.symbols.call_non_blocking(args, args.length, res, res.length);
  if (status !== 0) {
    throw Error('Invalid')
  }

  return new TextDecoder().decode(res)
}

console.log(await invoke_ffi())

Rust FFI library:

use std::{thread, time};

#[no_mangle]
pub extern "C" fn call_non_blocking(
    args: *const u8,
    args_len: usize,
    res: *mut u8,
    res_len: usize,
) -> u32 {
    let args = unsafe { std::slice::from_raw_parts(args, args_len) };

    let res = unsafe { std::slice::from_raw_parts_mut(res, res_len) };

    // Without this line, it does not segfault
    thread::sleep(time::Duration::from_millis(30));

    res.copy_from_slice(args);
    0
}

@rracariu
Copy link
Author

rracariu commented Nov 9, 2021

The output of the above is:

deno run -A --unstable ./ffi.js 
A
Segmentation fault

@rracariu rracariu changed the title Deno 1.15.3 - Segmentation fault at exit Segmentation fault at exit Nov 9, 2021
@rracariu
Copy link
Author

rracariu commented Nov 9, 2021

This reproduces with latest 1.16.0

@bartlomieju bartlomieju removed the needs info needs further information to be properly triaged label Nov 10, 2021
@rracariu
Copy link
Author

Can you please prioritize this issue?

It affects running unit tests in CI because of the non zero return code.

@bartlomieju bartlomieju added this to the 1.17.0 milestone Nov 21, 2021
@andreubotella
Copy link
Contributor

andreubotella commented Nov 21, 2021

If you register an async function as the listener to the unload event, neither Deno nor browsers will wait until the function's promise has resolved before exiting. I suspect this crash is because, as the main thread closes and the V8 isolate terminates, any memory owned by the isolate gets freed, including the buffer passed to the FFI call. But the non-blocking FFI thread expects the buffer to remain alive.

I suspect this can also be an issue with terminating/closing workers.

@andreubotella
Copy link
Contributor

Related to #12341.

@bnoordhuis
Copy link
Contributor

I suspect this crash is because, as the main thread closes and the V8 isolate terminates, any memory owned by the isolate gets freed, including the buffer passed to the FFI call.

To confirm: this is indeed what happens. I would hesitate to call it a bug but it's an unfortunate interaction between subsystems.

The synchronous nature of "unload" shouldn't change and rejecting async functions is sub-optimal. Deno could perhaps print a warning if the promise is still pending.

Example:

// not a problem: no await points, effectively synchronous
addEventListener("unload", async () => console.log("bye"))

// this however _is_ a problem and should probably warn
addEventListener("unload", () => new Promise(k => setTimeout(k)))

@rracariu
Copy link
Author

Not executing a callback is fine, crashing it is not.
This issue does not reproduce on Windows, so it is most likely a sequence of events that is different on those platforms that gives a different result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working correctly FFI Related to Foreign Function Interface APIs
Projects
None yet
Development

No branches or pull requests

5 participants