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

Asynchronous functions are unsound in the presence of the garbage collector #1338

Closed
shepmaster opened this issue Oct 7, 2022 · 0 comments · Fixed by #1339
Closed

Asynchronous functions are unsound in the presence of the garbage collector #1338

shepmaster opened this issue Oct 7, 2022 · 0 comments · Fixed by #1339

Comments

@shepmaster
Copy link

Actual Output

  1. The infinite loop prints a few times
  2. The garbage collector runs (forced in this case, randomly in real production code)
  3. The value is dropped ⚠️
  4. The loop continues execution, reading from the dropped value ⚠️ ⚠️ ⚠️
Awesome(100) has been created
Awesome(100) is idling...
Awesome(100) is idling...
Awesome(100) is idling...
Awesome(100) is idling...
GC request (true)
GC request (false)
Awesome(99) has been dropped
Awesome(48) is idling...
Awesome(48) is idling...
Awesome(48) is idling...

Expected

I expected the call to runForever to keep a reference to the awesome instance alive until the function finished execution.

Steps to reproduce

lib.rs

use napi_derive::napi;
use std::time::Duration;
use tokio::time;

#[napi]
#[derive(Debug)]
pub struct Awesome(u8);

#[napi]
impl Awesome {
    #[napi(constructor)]
    pub fn new() -> Self {
        let this = Self(100);
        eprintln!("{this:?} has been created");
        this
    }

    #[napi]
    pub async fn run_forever(&self) {
        let mut i = time::interval(Duration::from_secs(1));
        loop {
            i.tick().await;
            eprintln!("{self:?} is idling...");
        }
    }
}

impl Drop for Awesome {
    fn drop(&mut self) {
        self.0 -= 1;
        eprintln!("{self:?} has been dropped")
    }
}

Cargo.toml

[package]
edition = "2021"
name = "napi-gc"
version = "0.0.0"

[lib]
crate-type = ["cdylib"]

[dependencies]
napi = { version = "2.10.0", default-features = false, features = ["napi8", "tokio_rt"] }
napi-derive = "2.9.1"
tokio = { version = "*", features = ["full"] }

[build-dependencies]
napi-build = "2.0.1"

[profile.release]
lto = true

run.js

const { Awesome } = require('./');

const awesome = new Awesome();

awesome.runForever().then(() => {
  console.log("runForever has exited");
});

setTimeout(() => {
  global.gc(true);
  console.log("GC request (true)");

  global.gc(false);
  console.log("GC request (false)");

  setTimeout(() => {
    process.exit();
  }, 3000);
}, 3000);

package.json

{
  "name": "napi-gc",
  "version": "0.0.0",
  "main": "index.js",
  "types": "index.d.ts",
  "napi": {
    "name": "napi-gc",
    "triples": {
      "defaults": false,
      "additional": [
        "aarch64-apple-darwin"
      ]
    }
  },
  "license": "MIT",
  "devDependencies": {
    "@napi-rs/cli": "^2.12.0",
    "ava": "^4.3.3"
  },
  "ava": {
    "timeout": "3m"
  },
  "engines": {
    "node": ">= 10"
  },
  "scripts": {
    "x": "node --expose-gc run",

    "artifacts": "napi artifacts",
    "build": "napi build --platform --release",
    "build:debug": "napi build --platform",
    "prepublishOnly": "napi prepublish -t npm",
    "test": "ava",
    "version": "napi version"
  },
  "packageManager": "yarn@3.2.4"
}

Running yarn run x.

Xaeroxe added a commit to Xaeroxe/napi-rs that referenced this issue Oct 7, 2022
Xaeroxe added a commit to Xaeroxe/napi-rs that referenced this issue Oct 7, 2022
Xaeroxe added a commit to Xaeroxe/napi-rs that referenced this issue Oct 7, 2022
Xaeroxe added a commit to Xaeroxe/napi-rs that referenced this issue Oct 9, 2022
Xaeroxe added a commit to Xaeroxe/napi-rs that referenced this issue Oct 9, 2022
Brooooooklyn pushed a commit to Xaeroxe/napi-rs that referenced this issue Nov 21, 2022
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

Successfully merging a pull request may close this issue.

1 participant