22use std:: {
33 ffi:: { c_char, c_int, c_void, CStr } ,
44 marker:: PhantomData ,
5+ panic:: { catch_unwind, resume_unwind} ,
56} ;
67
78use 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) ]
199224pub 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) ]
312339pub 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