Skip to content

Commit e278448

Browse files
committed
fix(native_tracer): Use the correct raw tracing signature and fix the build isssues
1 parent c21d770 commit e278448

File tree

3 files changed

+66
-28
lines changed

3 files changed

+66
-28
lines changed

ext/native_tracer/Cargo.toml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1+
# Cargo.toml
12
[package]
23
name = "codetracer_ruby_recorder"
4+
description = "Native Ruby module for generating CodeTracer trace files"
35
version = "0.1.0"
4-
edition = "2021" # latest stable Rust edition
5-
description = "Native Ruby tracer using rb_add_event_hook2"
6-
7-
[lib]
6+
edition = "2021"
87
crate-type = ["cdylib"]
8+
build = "build.rs"
99

1010
[dependencies]
1111
rb-sys = "0.9"
1212
runtime_tracing = "0.10.0"
13+
14+
[build-dependencies]
15+
rb-sys-env = "0.2"

ext/native_tracer/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() -> Result<(), Box<dyn std::error::Error>> {
2+
rb_sys_env::activate()?;
3+
Ok(())
4+
}

ext/native_tracer/src/lib.rs

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,64 @@
1-
use std::ffi::CStr;
2-
use std::os::raw::{c_char, c_int};
3-
use rb_sys::{VALUE, ID, rb_add_event_hook2, rb_event_flag_t, RUBY_EVENT_LINE, rb_sourcefile, rb_sourceline, RUBY_EVENT_HOOK_FLAG_RAW_ARG};
4-
use runtime_tracing::{TraceWriter, StepRecord};
5-
6-
static mut WRITER: Option<TraceWriter<std::fs::File>> = None;
7-
8-
extern "C" fn event_hook(ev: rb_event_flag_t, _data: VALUE, _self: VALUE, _mid: ID, _klass: VALUE) {
9-
if ev & RUBY_EVENT_LINE as rb_event_flag_t != 0 {
10-
unsafe {
11-
if let Some(writer) = WRITER.as_mut() {
12-
let line: u32 = rb_sourceline() as u32;
13-
let file_ptr: *const c_char = rb_sourcefile();
14-
if !file_ptr.is_null() {
15-
if let Ok(path) = CStr::from_ptr(file_ptr).to_str() {
16-
let rec = StepRecord { path: path.into(), line };
17-
let _ = writer.write_step(&rec);
18-
}
19-
}
20-
}
1+
#![allow(clippy::missing_safety_doc)]
2+
3+
use std::{ffi::CStr, mem::transmute, os::raw::c_char};
4+
5+
use rb_sys::{
6+
// frequently used public items
7+
rb_add_event_hook2, rb_event_flag_t,
8+
rb_event_hook_flag_t::RUBY_EVENT_HOOK_FLAG_RAW_ARG,
9+
ID, VALUE, RUBY_EVENT_LINE,
10+
11+
// the raw-trace-API symbols live in the generated `bindings` module
12+
bindings::{
13+
rb_trace_arg_t, // struct rb_trace_arg
14+
rb_tracearg_event_flag, // event kind helpers
15+
rb_tracearg_lineno,
16+
rb_tracearg_path,
17+
},
18+
};
19+
20+
/// Raw-argument callback (Ruby will call it when we set
21+
/// `RUBY_EVENT_HOOK_FLAG_RAW_ARG`).
22+
///
23+
/// C prototype:
24+
/// ```c
25+
/// void (*)(VALUE data, rb_trace_arg_t *arg);
26+
/// ```
27+
unsafe extern "C" fn event_hook_raw(_data: VALUE, arg: *mut rb_trace_arg_t) {
28+
if arg.is_null() {
29+
return;
30+
}
31+
32+
let ev: rb_event_flag_t = rb_tracearg_event_flag(arg);
33+
if (ev & RUBY_EVENT_LINE) == 0 {
34+
return;
35+
}
36+
37+
let path_ptr = rb_tracearg_path(arg) as *const c_char;
38+
let line = rb_tracearg_lineno(arg) as u32;
39+
40+
if !path_ptr.is_null() {
41+
if let Ok(path) = CStr::from_ptr(path_ptr).to_str() {
42+
println!("Path: {path}, Line: {line}");
2143
}
2244
}
2345
}
2446

2547
#[no_mangle]
2648
pub extern "C" fn Init_codetracer_ruby_recorder() {
2749
unsafe {
28-
let out = std::env::var("CODETRACER_DB_TRACE_PATH").unwrap_or_else(|_| "trace.json".to_string());
29-
let file = std::fs::File::create(out).expect("failed to create trace output");
30-
WRITER = Some(TraceWriter::new(file));
31-
rb_add_event_hook2(Some(event_hook), RUBY_EVENT_LINE as rb_event_flag_t, 0 as VALUE, RUBY_EVENT_HOOK_FLAG_RAW_ARG as i32);
50+
// rb_add_event_hook2’s first parameter is a function pointer with the
51+
// classic five-argument signature. We cast our raw callback to that
52+
// type via an intermediate variable so the sizes match.
53+
let raw_cb: unsafe extern "C" fn(VALUE, *mut rb_trace_arg_t) = event_hook_raw;
54+
let cb: unsafe extern "C" fn(rb_event_flag_t, VALUE, VALUE, ID, VALUE) =
55+
transmute(raw_cb);
56+
57+
rb_add_event_hook2(
58+
Some(cb), // callback (now cast)
59+
RUBY_EVENT_LINE, // which events
60+
0, // user data
61+
RUBY_EVENT_HOOK_FLAG_RAW_ARG,
62+
);
3263
}
3364
}

0 commit comments

Comments
 (0)