Skip to content

Commit dfa7d9b

Browse files
Introduce TracePtr for Send and Syncness
This allows us to both - retain provenance throughout - describe why these are Send and Sync - progressively reduce errors by reducing the conflation of pointers
1 parent bc6ba8e commit dfa7d9b

File tree

1 file changed

+110
-15
lines changed

1 file changed

+110
-15
lines changed

src/capture.rs

+110-15
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use crate::resolve;
33
use crate::PrintFmt;
44
use crate::{resolve_frame, trace, BacktraceFmt, Symbol, SymbolName};
5-
use std::ffi::c_void;
5+
use core::ffi::c_void;
66
use std::fmt;
77
use std::path::{Path, PathBuf};
88
use std::prelude::v1::*;
@@ -29,6 +29,101 @@ pub struct Backtrace {
2929
frames: Vec<BacktraceFrame>,
3030
}
3131

32+
#[derive(Clone, Copy)]
33+
struct TracePtr(*mut c_void);
34+
/// SAFETY: These pointers are always valid within a process and are not used for mutation.
35+
unsafe impl Send for TracePtr {}
36+
/// SAFETY: These pointers are always valid within a process and are not used for mutation.
37+
unsafe impl Sync for TracePtr {}
38+
39+
impl TracePtr {
40+
fn into_void(self) -> *mut c_void {
41+
self.0
42+
}
43+
#[cfg(feature = "serde")]
44+
fn from_addr(addr: usize) -> Self {
45+
TracePtr(addr as *mut c_void)
46+
}
47+
}
48+
49+
#[cfg(feature = "serde")]
50+
impl<'de> Deserialize<'de> for TracePtr {
51+
#[inline]
52+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
53+
where
54+
D: serde::Deserializer<'de>,
55+
{
56+
struct PrimitiveVisitor;
57+
58+
impl<'de> serde::de::Visitor<'de> for PrimitiveVisitor {
59+
type Value = TracePtr;
60+
61+
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
62+
formatter.write_str("usize")
63+
}
64+
65+
#[inline]
66+
fn visit_u8<E>(self, v: u8) -> Result<Self::Value, E>
67+
where
68+
E: serde::de::Error,
69+
{
70+
Ok(TracePtr(v as usize as *mut c_void))
71+
}
72+
73+
#[inline]
74+
fn visit_u16<E>(self, v: u16) -> Result<Self::Value, E>
75+
where
76+
E: serde::de::Error,
77+
{
78+
Ok(TracePtr(v as usize as *mut c_void))
79+
}
80+
81+
#[inline]
82+
fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
83+
where
84+
E: serde::de::Error,
85+
{
86+
if usize::BITS >= 32 {
87+
Ok(TracePtr(v as usize as *mut c_void))
88+
} else {
89+
Err(E::invalid_type(
90+
serde::de::Unexpected::Unsigned(v as _),
91+
&self,
92+
))
93+
}
94+
}
95+
96+
#[inline]
97+
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
98+
where
99+
E: serde::de::Error,
100+
{
101+
if usize::BITS >= 64 {
102+
Ok(TracePtr(v as usize as *mut c_void))
103+
} else {
104+
Err(E::invalid_type(
105+
serde::de::Unexpected::Unsigned(v as _),
106+
&self,
107+
))
108+
}
109+
}
110+
}
111+
112+
deserializer.deserialize_u64(PrimitiveVisitor)
113+
}
114+
}
115+
116+
#[cfg(feature = "serde")]
117+
impl Serialize for TracePtr {
118+
#[inline]
119+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
120+
where
121+
S: serde::ser::Serializer,
122+
{
123+
serializer.serialize_u64(self.0 as usize as u64)
124+
}
125+
}
126+
32127
fn _assert_send_sync() {
33128
fn _assert<T: Send + Sync>() {}
34129
_assert::<Backtrace>();
@@ -54,9 +149,9 @@ enum Frame {
54149
Raw(crate::Frame),
55150
#[cfg(feature = "serde")]
56151
Deserialized {
57-
ip: usize,
58-
symbol_address: usize,
59-
module_base_address: Option<usize>,
152+
ip: TracePtr,
153+
symbol_address: TracePtr,
154+
module_base_address: Option<TracePtr>,
60155
},
61156
}
62157

@@ -65,15 +160,15 @@ impl Frame {
65160
match *self {
66161
Frame::Raw(ref f) => f.ip(),
67162
#[cfg(feature = "serde")]
68-
Frame::Deserialized { ip, .. } => ip as *mut c_void,
163+
Frame::Deserialized { ip, .. } => ip.into_void(),
69164
}
70165
}
71166

72167
fn symbol_address(&self) -> *mut c_void {
73168
match *self {
74169
Frame::Raw(ref f) => f.symbol_address(),
75170
#[cfg(feature = "serde")]
76-
Frame::Deserialized { symbol_address, .. } => symbol_address as *mut c_void,
171+
Frame::Deserialized { symbol_address, .. } => symbol_address.into_void(),
77172
}
78173
}
79174

@@ -84,7 +179,7 @@ impl Frame {
84179
Frame::Deserialized {
85180
module_base_address,
86181
..
87-
} => module_base_address.map(|addr| addr as *mut c_void),
182+
} => module_base_address.map(|addr| addr.into_void()),
88183
}
89184
}
90185

@@ -94,7 +189,7 @@ impl Frame {
94189
let sym = |symbol: &Symbol| {
95190
symbols.push(BacktraceSymbol {
96191
name: symbol.name().map(|m| m.as_bytes().to_vec()),
97-
addr: symbol.addr().map(|a| a as usize),
192+
addr: symbol.addr().map(TracePtr),
98193
filename: symbol.filename().map(|m| m.to_owned()),
99194
lineno: symbol.lineno(),
100195
colno: symbol.colno(),
@@ -104,7 +199,7 @@ impl Frame {
104199
Frame::Raw(ref f) => resolve_frame(f, sym),
105200
#[cfg(feature = "serde")]
106201
Frame::Deserialized { ip, .. } => {
107-
resolve(ip as *mut c_void, sym);
202+
resolve(ip.into_void(), sym);
108203
}
109204
}
110205
symbols
@@ -124,7 +219,7 @@ impl Frame {
124219
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
125220
pub struct BacktraceSymbol {
126221
name: Option<Vec<u8>>,
127-
addr: Option<usize>,
222+
addr: Option<TracePtr>,
128223
filename: Option<PathBuf>,
129224
lineno: Option<u32>,
130225
colno: Option<u32>,
@@ -347,7 +442,7 @@ impl BacktraceSymbol {
347442
/// This function requires the `std` feature of the `backtrace` crate to be
348443
/// enabled, and the `std` feature is enabled by default.
349444
pub fn addr(&self) -> Option<*mut c_void> {
350-
self.addr.map(|s| s as *mut c_void)
445+
self.addr.map(|s| s.into_void())
351446
}
352447

353448
/// Same as `Symbol::filename`
@@ -468,7 +563,7 @@ mod serde_impls {
468563
SerializedFrame {
469564
ip: frame.ip() as usize,
470565
symbol_address: frame.symbol_address() as usize,
471-
module_base_address: frame.module_base_address().map(|addr| addr as usize),
566+
module_base_address: frame.module_base_address().map(|sym_a| sym_a as usize),
472567
symbols: symbols.clone(),
473568
}
474569
.serialize(s)
@@ -483,9 +578,9 @@ mod serde_impls {
483578
let frame: SerializedFrame = SerializedFrame::deserialize(d)?;
484579
Ok(BacktraceFrame {
485580
frame: Frame::Deserialized {
486-
ip: frame.ip,
487-
symbol_address: frame.symbol_address,
488-
module_base_address: frame.module_base_address,
581+
ip: TracePtr::from_addr(frame.ip),
582+
symbol_address: TracePtr::from_addr(frame.symbol_address),
583+
module_base_address: frame.module_base_address.map(TracePtr::from_addr),
489584
},
490585
symbols: frame.symbols,
491586
})

0 commit comments

Comments
 (0)