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:
RUST_BACKTRACE=1 and DEBUG=truetest.js file to print the output from the moduleBuild 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With