Skip to content

Commit b408b98

Browse files
committed
rust/ffi: rust friendly wrapper around thread init callback
Provide a Rust safe and friendly wrapper for registering a thread init callback, for example: register_init_callback(|tv: *mut ThreadVars| { }) For now, the raw pointer to the ThreadVars is provided, but we may want to wrap that at some point.
1 parent beedc43 commit b408b98

2 files changed

Lines changed: 67 additions & 0 deletions

File tree

rust/ffi/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub mod debug;
1919
pub mod eve;
2020
pub mod jsonbuilder;
2121
pub mod plugin;
22+
pub mod thread;
2223

2324
pub const IPPROTO_TCP: u8 = 6;
2425
pub const IPPROTO_UDP: u8 = 17;

rust/ffi/src/thread.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/* Copyright (C) 2026 Open Information Security Foundation
2+
*
3+
* You can copy, redistribute or modify this Program under the terms of
4+
* the GNU General Public License version 2 as published by the Free
5+
* Software Foundation.
6+
*
7+
* This program is distributed in the hope that it will be useful,
8+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
* GNU General Public License for more details.
11+
*
12+
* You should have received a copy of the GNU General Public License
13+
* version 2 along with this program; if not, write to the Free Software
14+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15+
* 02110-1301, USA.
16+
*/
17+
18+
use std::os::raw::c_void;
19+
20+
use suricata_sys::sys::SCThreadRegisterInitCallback;
21+
use suricata_sys::sys::ThreadVars;
22+
23+
/// Register a thread init callback.
24+
///
25+
/// The callback is invoked once for each thread initialized during
26+
/// Suricata startup.
27+
///
28+
/// # Example
29+
///
30+
/// ```no_run
31+
/// use suricata_ffi::thread;
32+
///
33+
/// thread::register_init_callback(|_tv| {
34+
/// // thread-local initialization can happen here
35+
/// }).expect("failed to register thread init callback");
36+
/// ```
37+
///
38+
/// # Safety
39+
///
40+
/// The callback receives a raw pointer from Suricata. This pointer is
41+
/// only valid for the duration of the callback invocation and must not
42+
/// be stored.
43+
///
44+
/// The callback must not panic.
45+
pub fn register_init_callback<F>(callback: F) -> Result<(), &'static str>
46+
where
47+
F: Fn(*mut ThreadVars) + Send + Sync + 'static,
48+
{
49+
let user = Box::into_raw(Box::new(callback)) as *mut c_void;
50+
if unsafe { SCThreadRegisterInitCallback(Some(callback_wrapper::<F>), user) } {
51+
Ok(())
52+
} else {
53+
unsafe {
54+
drop(Box::from_raw(user as *mut F));
55+
}
56+
Err("Failed to register thread init callback")
57+
}
58+
}
59+
60+
unsafe extern "C" fn callback_wrapper<F>(tv: *mut ThreadVars, user: *mut c_void)
61+
where
62+
F: Fn(*mut ThreadVars) + Send + Sync + 'static,
63+
{
64+
let callback = &*(user as *const F);
65+
callback(tv);
66+
}

0 commit comments

Comments
 (0)