-
Notifications
You must be signed in to change notification settings - Fork 11
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
Sig 11 #32
Comments
Narrowing it down, I believe it has either something to do with my test setup, or glibc. I created a Java application and tried loading the generated That said, compiling the JNI bindings for Android and everything runs well, except an occasional SIG 11 (seemingly the same problem that the GuardianProject's lib.rs (Final JNI bindings for Java/Android)#![allow(non_snake_case)]
extern crate tor_sys;
use jni::JNIEnv;
use jni::objects::{JClass, JList, JString, JObject};
use std::ffi::{CString, c_void};
use jni::sys::jstring;
/*
* Success: Returns empty jstring
* Error: Returns non-empty jstring (error message to throw TorManagerException)
**/
#[no_mangle]
pub extern "system" fn Java_io_matthewnelson_kmp_tor_KmpTorLoaderJvm_runLines(
env: JNIEnv,
_class: JClass,
// lines are a list of of strings to be run, already configured from kotlin side:
// ex: [ "--ControlPortWriteToFile", "/path/to/file" ]
lines: JObject // JList
) -> jstring {
let mut verify: Vec<String> = vec![
String::from("tor"), String::from("--verify-config"),
];
let mut run: Vec<String> = vec![
String::from("tor"),
];
let lines: JList = env.get_list(lines).expect("expected List<String>").into();
for i in 0..lines.size().unwrap() {
let line = JString::from(lines.get(i.into()).expect("expected a String").unwrap());
verify.push(env.get_string(line.clone()).unwrap().into());
run.push(env.get_string(line.clone()).unwrap().into());
}
let verify: Vec<_> = verify.into_iter().map(|s| CString::new(s).unwrap()).collect();
let verify: Vec<_> = verify.iter().map(|s| s.as_ptr()).collect();
let run: Vec<_> = run.into_iter().map(|s| CString::new(s).unwrap()).collect();
let run: Vec<_> = run.iter().map(|s| s.as_ptr()).collect();
let config = unsafe {
tor_sys::tor_main_configuration_new()
};
if config.is_null() {
return env.new_string("TorConfig was null.").unwrap().into_inner();
}
let result = unsafe {
// set lines to be verified
tor_sys::tor_main_configuration_set_command_line(
config,
verify.len() as i32,
verify.as_ptr()
)
};
if result != 0 {
return prepare_err_msg(config, &env, "Failed to set args for verification.");
}
let result = unsafe {
// run lines to verify
tor_sys::tor_run_main(config)
};
if result != 0 {
return prepare_err_msg(config, &env, "Failed to verify args. Tor does not like a setting.");
}
let result = unsafe {
// set lines to be run
tor_sys::tor_main_configuration_set_command_line(
config,
run.len() as i32,
run.as_ptr()
)
};
if result != 0 {
return prepare_err_msg(config, &env, "Failed to set args to run.");
}
let result = unsafe {
// run lines
// This is runBlocking on the current Thread (which is handled kotlin side)
tor_sys::tor_run_main(config)
};
if result != 0 {
return prepare_err_msg(config, &env, "Failed to run args.");
}
unsafe {
// release config from memory
tor_sys::tor_main_configuration_free(config);
}
return env.new_string("").unwrap().into_inner();
}
fn prepare_err_msg(config: *mut c_void, env: &JNIEnv, msg: &str) -> jstring {
unsafe {
tor_sys::tor_main_configuration_free(config)
};
return env.new_string(msg).unwrap().into_inner();
} Android Functionality: |
I would try adding some code to enforce only one instance of Tor running at a time: unfortunately Tor internally uses a lot of You could implement this in Rust (just use a There's still one issue though, which is that if your Tor instance doesn't exit cleanly there's basically no way to restart it afterwards because the shared state will be corrupted. The only workaround I could think of involves putting all of the Tor code in a separate shared object which is not linked to your main binary, but it's just loaded at runtime using Unfortunately that means that you would have to ship an extra shared lib with your binary (I don't think you can embed it inside), which is not ideal. Also, I don't know if recent mobile OSs let you load libraries at runtime, but I'm afraid they might not for safety reasons. So in the end I only made a prototype which I pushed to this branch, but I've never spent the time to clean it up and merge it. I could do it if there's interest for it though. Unrelated, but something you could find useful to debug: to rule out glibc issues you could try building against musl. It's not officially "supported" because I don't think we test it in the CI, but I remember trying it a while back (musl on x86_64) and it was working fine. |
Yes, the underlying abstract class
Amazing... Gave me the idea to let the Jni loader class where final KmpTorLoaderJvm (for Android, still need to work out Java)actual class KmpTorLoaderJvm(provider: TorConfigProviderAndroid): KmpTorLoader(provider) {
@Throws(TorManagerException::class, CancellationException::class)
override suspend fun startTor(configLines: List<String>) {
val exMessage = KmpTorLoaderJni().runLines(configLines)
if (exMessage.isNotEmpty()) {
throw TorManagerException(exMessage)
}
}
}
private class KmpTorLoaderJni {
init {
System.loadLibrary("KmpTor")
}
// Had to update method signature in Rust to:
// Java_io_matthewnelson_kmp_tor_KmpTorLoaderJni_runLines(
external fun runLines(lines: List<String>): String
}
Will let ya know. |
Compiling JNI bindings atop libtor-sys and I keep getting intermittent
Tor 0.4.6.9 died: Caught signal 11
crashes. Not entirely sure if this is attributed to something with libtor-sys, or JVM side, but I feel like I'm losing my mind trying to debug this.JVM Test simply starts Tor, then cycles a restart a couple times at 5s intervals. It sometimes fails immediately, sometimes makes it through start and then 1 restart cycle.
Any suggestions would be greatly appreciated.
lib.rs (work in progress, lol)
Cargo.toml
Kotlin Multiplatform JVM Native Loader
Jvm test output 1 (linuxx64, failure on first restart called)
Jvm test output 2 (linuxx64, failure mid run after successful restart)
The text was updated successfully, but these errors were encountered: