Skip to content
This repository was archived by the owner on Oct 18, 2023. It is now read-only.

Commit 9ec0c2f

Browse files
authored
catch panics in FFI and print BT (#696)
1 parent 304593f commit 9ec0c2f

File tree

1 file changed

+72
-39
lines changed

1 file changed

+72
-39
lines changed

sqld-libsql-bindings/src/wal_hook.rs

Lines changed: 72 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use std::{
33
ffi::{c_char, c_int, c_void, CStr},
44
marker::PhantomData,
5+
panic::{catch_unwind, resume_unwind},
56
};
67

78
use crate::ffi::{libsql_wal_methods, sqlite3, sqlite3_file, sqlite3_vfs, types::*, PgHdr, Wal};
@@ -195,6 +196,30 @@ impl<T: WalHook> WalMethodsHook<T> {
195196
}
196197
}
197198

199+
macro_rules! catch_panic {
200+
($($body:tt)*) => {
201+
let ret = catch_unwind(move || {
202+
$($body)*
203+
});
204+
205+
match ret {
206+
Ok(x) => x,
207+
Err(e) => {
208+
let error = if let Some(s) = e.downcast_ref::<String>() {
209+
s.as_str()
210+
} else if let Some(s) = e.downcast_ref::<&str>() {
211+
s
212+
} else {
213+
"unknown"
214+
};
215+
let bt = std::backtrace::Backtrace::force_capture();
216+
tracing::error!("panic in call to xframe: {error}:\n{bt}");
217+
resume_unwind(e)
218+
}
219+
}
220+
};
221+
}
222+
198223
#[allow(non_snake_case)]
199224
pub extern "C" fn xOpen<T: WalHook>(
200225
vfs: *mut sqlite3_vfs,
@@ -295,11 +320,13 @@ pub extern "C" fn xUndo<T: WalHook>(
295320
func: Option<unsafe extern "C" fn(*mut c_void, u32) -> i32>,
296321
undo_ctx: *mut c_void,
297322
) -> i32 {
298-
assert!(!wal.is_null());
299-
let wal = unsafe { &mut *wal };
300-
let orig_methods = get_orig_methods::<T>(wal);
301-
let orig_xundo = orig_methods.xUndo.unwrap();
302-
T::on_undo(wal, func, undo_ctx, orig_xundo)
323+
catch_panic! {
324+
assert!(!wal.is_null());
325+
let wal = unsafe { &mut *wal };
326+
let orig_methods = get_orig_methods::<T>(wal);
327+
let orig_xundo = orig_methods.xUndo.unwrap();
328+
T::on_undo(wal, func, undo_ctx, orig_xundo)
329+
}
303330
}
304331

305332
#[allow(non_snake_case)]
@@ -310,10 +337,12 @@ pub extern "C" fn xSavepoint<T: WalHook>(wal: *mut Wal, wal_data: *mut u32) {
310337

311338
#[allow(non_snake_case)]
312339
pub extern "C" fn xSavepointUndo<T: WalHook>(wal: *mut Wal, wal_data: *mut u32) -> i32 {
313-
let wal = unsafe { &mut *wal };
314-
let orig_methods = get_orig_methods::<T>(wal);
315-
let orig_xsavepointundo = orig_methods.xSavepointUndo.unwrap();
316-
T::on_savepoint_undo(wal, wal_data, orig_xsavepointundo)
340+
catch_panic! {
341+
let wal = unsafe { &mut *wal };
342+
let orig_methods = get_orig_methods::<T>(wal);
343+
let orig_xsavepointundo = orig_methods.xSavepointUndo.unwrap();
344+
T::on_savepoint_undo(wal, wal_data, orig_xsavepointundo)
345+
}
317346
}
318347

319348
#[allow(non_snake_case)]
@@ -325,20 +354,22 @@ pub extern "C" fn xFrames<T: WalHook>(
325354
is_commit: c_int,
326355
sync_flags: c_int,
327356
) -> c_int {
328-
assert!(!wal.is_null());
329-
let wal = unsafe { &mut *wal };
330-
let orig_methods = get_orig_methods::<T>(wal);
331-
let orig_xframe = orig_methods.xFrames.unwrap();
332-
333-
T::on_frames(
334-
wal,
335-
page_size,
336-
page_headers,
337-
size_after,
338-
is_commit,
339-
sync_flags,
340-
orig_xframe,
341-
)
357+
catch_panic! {
358+
assert!(!wal.is_null());
359+
let wal = unsafe { &mut *wal };
360+
let orig_methods = get_orig_methods::<T>(wal);
361+
let orig_xframe = orig_methods.xFrames.unwrap();
362+
363+
T::on_frames(
364+
wal,
365+
page_size,
366+
page_headers,
367+
size_after,
368+
is_commit,
369+
sync_flags,
370+
orig_xframe,
371+
)
372+
}
342373
}
343374

344375
#[tracing::instrument(skip(wal, db))]
@@ -355,22 +386,24 @@ pub extern "C" fn xCheckpoint<T: WalHook>(
355386
frames_in_wal: *mut c_int,
356387
backfilled_frames: *mut c_int,
357388
) -> i32 {
358-
let wal = unsafe { &mut *wal };
359-
let orig_methods = get_orig_methods::<T>(wal);
360-
let orig_xcheckpoint = orig_methods.xCheckpoint.unwrap();
361-
T::on_checkpoint(
362-
wal,
363-
db,
364-
emode,
365-
busy_handler,
366-
busy_arg,
367-
sync_flags,
368-
n_buf,
369-
z_buf,
370-
frames_in_wal,
371-
backfilled_frames,
372-
orig_xcheckpoint,
373-
)
389+
catch_panic! {
390+
let wal = unsafe { &mut *wal };
391+
let orig_methods = get_orig_methods::<T>(wal);
392+
let orig_xcheckpoint = orig_methods.xCheckpoint.unwrap();
393+
T::on_checkpoint(
394+
wal,
395+
db,
396+
emode,
397+
busy_handler,
398+
busy_arg,
399+
sync_flags,
400+
n_buf,
401+
z_buf,
402+
frames_in_wal,
403+
backfilled_frames,
404+
orig_xcheckpoint,
405+
)
406+
}
374407
}
375408

376409
#[allow(non_snake_case)]

0 commit comments

Comments
 (0)