2
2
use std:: {
3
3
ffi:: { c_char, c_int, c_void, CStr } ,
4
4
marker:: PhantomData ,
5
+ panic:: { catch_unwind, resume_unwind} ,
5
6
} ;
6
7
7
8
use crate :: ffi:: { libsql_wal_methods, sqlite3, sqlite3_file, sqlite3_vfs, types:: * , PgHdr , Wal } ;
@@ -195,6 +196,30 @@ impl<T: WalHook> WalMethodsHook<T> {
195
196
}
196
197
}
197
198
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
+
198
223
#[ allow( non_snake_case) ]
199
224
pub extern "C" fn xOpen < T : WalHook > (
200
225
vfs : * mut sqlite3_vfs ,
@@ -295,11 +320,13 @@ pub extern "C" fn xUndo<T: WalHook>(
295
320
func : Option < unsafe extern "C" fn ( * mut c_void , u32 ) -> i32 > ,
296
321
undo_ctx : * mut c_void ,
297
322
) -> 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
+ }
303
330
}
304
331
305
332
#[ allow( non_snake_case) ]
@@ -310,10 +337,12 @@ pub extern "C" fn xSavepoint<T: WalHook>(wal: *mut Wal, wal_data: *mut u32) {
310
337
311
338
#[ allow( non_snake_case) ]
312
339
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
+ }
317
346
}
318
347
319
348
#[ allow( non_snake_case) ]
@@ -325,20 +354,22 @@ pub extern "C" fn xFrames<T: WalHook>(
325
354
is_commit : c_int ,
326
355
sync_flags : c_int ,
327
356
) -> 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
+ }
342
373
}
343
374
344
375
#[ tracing:: instrument( skip( wal, db) ) ]
@@ -355,22 +386,24 @@ pub extern "C" fn xCheckpoint<T: WalHook>(
355
386
frames_in_wal : * mut c_int ,
356
387
backfilled_frames : * mut c_int ,
357
388
) -> 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
+ }
374
407
}
375
408
376
409
#[ allow( non_snake_case) ]
0 commit comments