Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get a backtrace or otherwise debug "failed to initiate panic" when using Rust with Neon bindings?

I have written a native Node module using Rust + Neon Bindings. The general purpose is to query a database, decrypt the results, and return a JSON array to Node. For some datasets this is working as expected, however for others it is causing a panic. I am attempting to debug it, however I can't figure out how to get a stacktrace. The only output is:

fatal runtime error: failed to initiate panic, error 5
    Abort trap: 6

My attempts to debug include:

  • including "backtrace" in the Cargo.toml
  • compiling without "--release"
  • setting RUST_BACKTRACE=1 and DEBUG=true
  • creating a test.js file to print the output from the module

Build output:

> neon build
neon info running cargo
  ... all the compilation steps.
  Finished dev [unoptimized + debuginfo] target(s) in 2m 17s
neon info generating native/index.node

Test file:

const Addon = require('./lib');
const addon = new Addon();
(async function() {
  console.log(`process.env.RUST_BACKTRACE = ${process.env.RUST_BACKTRACE}`);
  const i = await addon.getData(237);
  console.log(i, i.length)
}());

Test output:

> RUST_BACKTRACE=1 DEBUG=true node test.js 
process.env.RUST_BACKTRACE = 1
fatal runtime error: failed to initiate panic, error 5
Abort trap: 6

For other values passed to addon.getData() I get back the JSON array of data as expected. The dataset that is failing is quite large so I haven't been able to determine any differences.

> rustc --version
rustc 1.38.0 (625451e37 2019-09-23)
> cargo --version
cargo 1.38.0 (23ef9a4ef 2019-08-20)
> node --version
v11.15.0
> neon version
0.3.1

I have implemented a synchronous version of the code, as well as asynchronous using this example. The async callback is converted into a Promise in ./lib/index.js. After updating the test.js to use the synchronous version of the code, I got the following output:

(node:45229) UnhandledPromiseRejectionWarning: Error: internal error in Neon module: called `Option::unwrap()` on a `None` value

I added a bunch of println!()s to my code and was able to find the error (a missing required property on a decrypted JSON object), but was never able to get a proper stack trace. It seems like Neon must be swallowing them in the async code.

like image 231
doublesharp Avatar asked Dec 03 '25 00:12

doublesharp


1 Answers

I ran into the same issue as you do, and for me I got it resolved by processing the result properly by using the match clause and use this method to handle the error results, so the callback will properly generate a NodeJS error on my side.

some of my snippet:

use std::sync::{Arc, Mutex};

use crate::utils::convert_uids_map;

use neon::prelude::*;

use dgraph_tonic::{DgraphError, Mutation, MutationResponse};
use dgraph_tonic::sync::{Mutate};

pub struct MutateTask<M> where M: Mutate {
  pub txn: Arc<Mutex<Option<M>>>,
  pub mu: Mutation,
}

impl<M> Task for MutateTask<M> where M: Mutate + 'static {
  type Output = MutationResponse;
  type Error = DgraphError;
  type JsEvent = JsValue;

  fn perform(&self) -> Result<Self::Output, Self::Error> {
    let mut mutex_guard = self.txn.lock().unwrap();
    let txn = mutex_guard.as_mut();
    match txn {
      Some(t) => t.mutate(self.mu.clone()),
      None => Err(DgraphError::EmptyTxn)
    }
  }

  fn complete(self, mut ctx: TaskContext, result: Result<Self::Output, Self::Error>) -> JsResult<Self::JsEvent> {
    match result {
      Ok(x) => Ok(convert_uids_map(&mut ctx, &x.uids).unwrap().upcast()),
      Err(e) => ctx.throw_error(format!("MutateTask Error - {:?}", e))
    }
  }
}

and then I got meaningful error to proceed:

(node:50781) UnhandledPromiseRejectionWarning: Error: MutateTask Error - GrpcError(CannotDoRequest(Status { code: Unknown, message: "key error: subject:\"_:dg.1759080630.67\" predicate:\"@timestamp\" object_value:<str_val:\"2020-04-28T02:22:19.570Z\" > : predicate \"@timestamp\": Has invalid characters" }))
(node:50781) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:50781) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
like image 169
Simon Liang Avatar answered Dec 04 '25 15:12

Simon Liang



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!