Skip to content

Commit 5b45014

Browse files
rustify :-D
1 parent 19d8c6c commit 5b45014

1 file changed

Lines changed: 41 additions & 28 deletions

File tree

profiling/src/io/mod.rs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,38 @@ use std::sync::atomic::{AtomicU64, Ordering};
1515
use std::sync::{Mutex, OnceLock};
1616
use std::time::Instant;
1717

18-
#[inline]
19-
unsafe fn get_errno() -> c_int {
20-
*libc::__errno_location()
18+
/// RAII guard that snapshots `errno` on creation and restores it on drop.
19+
///
20+
/// I/O profiling wrappers intercept libc calls and run additional logic (timing, sampling) that
21+
/// can clobber `errno`. Callers of the original syscall expect `errno` to reflect the syscall
22+
/// result, not our wrapper internals. Create an `ErrnoBackup` right after the original syscall
23+
/// returns and let it live until the end of the wrapper function, its `Drop` impl will
24+
/// transparently restore the original `errno` value.
25+
struct ErrnoBackup {
26+
errno: c_int,
27+
location: *mut c_int,
28+
}
29+
30+
impl ErrnoBackup {
31+
/// Snapshots the current `errno` value.
32+
#[inline]
33+
unsafe fn new() -> Self {
34+
let location = libc::__errno_location();
35+
Self {
36+
errno: *location,
37+
location,
38+
}
39+
}
2140
}
2241

23-
#[inline]
24-
unsafe fn set_errno(errno: c_int) {
25-
*libc::__errno_location() = errno;
42+
impl Drop for ErrnoBackup {
43+
/// Restores `errno` value.
44+
#[inline]
45+
fn drop(&mut self) {
46+
unsafe {
47+
*self.location = self.errno;
48+
}
49+
}
2650
}
2751

2852
static mut ORIG_POLL: unsafe extern "C" fn(*mut libc::pollfd, u64, c_int) -> i32 = libc::poll;
@@ -37,7 +61,7 @@ static mut ORIG_POLL: unsafe extern "C" fn(*mut libc::pollfd, u64, c_int) -> i32
3761
unsafe extern "C" fn observed_poll(fds: *mut libc::pollfd, nfds: u64, timeout: c_int) -> i32 {
3862
let start = Instant::now();
3963
let ret = ORIG_POLL(fds, nfds, timeout);
40-
let ret_errno = get_errno();
64+
let _errno_backup = ErrnoBackup::new();
4165
let duration = start.elapsed();
4266

4367
if !fds.is_null() {
@@ -73,7 +97,6 @@ unsafe extern "C" fn observed_poll(fds: *mut libc::pollfd, nfds: u64, timeout: c
7397
}
7498
}
7599

76-
set_errno(ret_errno);
77100
ret
78101
}
79102

@@ -87,7 +110,7 @@ unsafe extern "C" fn observed_recv(
87110
) -> isize {
88111
let start = Instant::now();
89112
let len = ORIG_RECV(socket, buf, length, flags);
90-
let ret_errno = get_errno();
113+
let _errno_backup = ErrnoBackup::new();
91114
let duration = start.elapsed();
92115

93116
let duration_nanos = duration.as_nanos() as u64;
@@ -102,7 +125,6 @@ unsafe extern "C" fn observed_recv(
102125
}
103126
}
104127

105-
set_errno(ret_errno);
106128
len
107129
}
108130

@@ -116,7 +138,7 @@ unsafe extern "C" fn observed_recvmsg(
116138
) -> isize {
117139
let start = Instant::now();
118140
let len = ORIG_RECVMSG(socket, msg, flags);
119-
let ret_errno = get_errno();
141+
let _errno_backup = ErrnoBackup::new();
120142
let duration = start.elapsed();
121143

122144
let duration_nanos = duration.as_nanos() as u64;
@@ -131,7 +153,6 @@ unsafe extern "C" fn observed_recvmsg(
131153
}
132154
}
133155

134-
set_errno(ret_errno);
135156
len
136157
}
137158

@@ -154,7 +175,7 @@ unsafe extern "C" fn observed_recvfrom(
154175
) -> isize {
155176
let start = Instant::now();
156177
let len = ORIG_RECVFROM(socket, buf, length, flags, address, address_len);
157-
let ret_errno = get_errno();
178+
let _errno_backup = ErrnoBackup::new();
158179
let duration = start.elapsed();
159180

160181
let duration_nanos = duration.as_nanos() as u64;
@@ -169,7 +190,6 @@ unsafe extern "C" fn observed_recvfrom(
169190
}
170191
}
171192

172-
set_errno(ret_errno);
173193
len
174194
}
175195

@@ -183,7 +203,7 @@ unsafe extern "C" fn observed_send(
183203
) -> isize {
184204
let start = Instant::now();
185205
let len = ORIG_SEND(socket, buf, length, flags);
186-
let ret_errno = get_errno();
206+
let _errno_backup = ErrnoBackup::new();
187207
let duration = start.elapsed();
188208

189209
let duration_nanos = duration.as_nanos() as u64;
@@ -198,7 +218,6 @@ unsafe extern "C" fn observed_send(
198218
}
199219
}
200220

201-
set_errno(ret_errno);
202221
len
203222
}
204223

@@ -211,7 +230,7 @@ unsafe extern "C" fn observed_sendmsg(
211230
) -> isize {
212231
let start = Instant::now();
213232
let len = ORIG_SENDMSG(socket, msg, flags);
214-
let ret_errno = get_errno();
233+
let _errno_backup = ErrnoBackup::new();
215234
let duration = start.elapsed();
216235

217236
let duration_nanos = duration.as_nanos() as u64;
@@ -226,7 +245,6 @@ unsafe extern "C" fn observed_sendmsg(
226245
}
227246
}
228247

229-
set_errno(ret_errno);
230248
len
231249
}
232250

@@ -244,7 +262,7 @@ unsafe extern "C" fn observed_fwrite(
244262
) -> usize {
245263
let start = Instant::now();
246264
let len = ORIG_FWRITE(ptr, size, nobj, stream);
247-
let ret_errno = get_errno();
265+
let _errno_backup = ErrnoBackup::new();
248266
let duration = start.elapsed();
249267

250268
let duration_nanos = duration.as_nanos() as u64;
@@ -258,15 +276,14 @@ unsafe extern "C" fn observed_fwrite(
258276
}
259277
}
260278

261-
set_errno(ret_errno);
262279
len
263280
}
264281

265282
static mut ORIG_WRITE: unsafe extern "C" fn(c_int, *const c_void, usize) -> isize = libc::write;
266283
unsafe extern "C" fn observed_write(fd: c_int, buf: *const c_void, count: usize) -> isize {
267284
let start = Instant::now();
268285
let len = ORIG_WRITE(fd, buf, count);
269-
let ret_errno = get_errno();
286+
let _errno_backup = ErrnoBackup::new();
270287
let duration = start.elapsed();
271288

272289
let duration_nanos = duration.as_nanos() as u64;
@@ -299,7 +316,6 @@ unsafe extern "C" fn observed_write(fd: c_int, buf: *const c_void, count: usize)
299316
}
300317
}
301318

302-
set_errno(ret_errno);
303319
len
304320
}
305321

@@ -316,7 +332,7 @@ unsafe extern "C" fn observed_fread(
316332
) -> usize {
317333
let start = Instant::now();
318334
let len = ORIG_FREAD(ptr, size, nobj, stream);
319-
let ret_errno = get_errno();
335+
let _errno_backup = ErrnoBackup::new();
320336
let duration = start.elapsed();
321337

322338
let duration_nanos = duration.as_nanos() as u64;
@@ -330,15 +346,14 @@ unsafe extern "C" fn observed_fread(
330346
}
331347
}
332348

333-
set_errno(ret_errno);
334349
len
335350
}
336351

337352
static mut ORIG_READ: unsafe extern "C" fn(c_int, *mut c_void, usize) -> isize = libc::read;
338353
unsafe extern "C" fn observed_read(fd: c_int, buf: *mut c_void, count: usize) -> isize {
339354
let start = Instant::now();
340355
let len = ORIG_READ(fd, buf, count);
341-
let ret_errno = get_errno();
356+
let _errno_backup = ErrnoBackup::new();
342357
let duration = start.elapsed();
343358

344359
let duration_nanos = duration.as_nanos() as u64;
@@ -369,19 +384,17 @@ unsafe extern "C" fn observed_read(fd: c_int, buf: *mut c_void, count: usize) ->
369384
}
370385
}
371386

372-
set_errno(ret_errno);
373387
len
374388
}
375389

376390
static mut ORIG_CLOSE: unsafe extern "C" fn(i32) -> i32 = libc::close;
377391
/// The sole purpose of this function is to remove the `fd` from the `FD_CACHE`
378392
unsafe extern "C" fn observed_close(fd: i32) -> i32 {
379393
let ret = ORIG_CLOSE(fd);
380-
let ret_errno = get_errno();
394+
let _errno_backup = ErrnoBackup::new();
381395
let cache = FD_CACHE.get_or_init(|| Mutex::new(HashMap::new()));
382396
let mut cache = cache.lock().unwrap();
383397
cache.remove(&fd);
384-
set_errno(ret_errno);
385398
ret
386399
}
387400

0 commit comments

Comments
 (0)