@@ -2373,6 +2373,19 @@ loUnlink connection oid
2373
2373
negError =<< c_lo_unlink c oid
2374
2374
2375
2375
2376
+ -- Reminder on `unsafe` FFI:
2377
+ --
2378
+ -- - `unsafe` calls MUST NOT do any IO!
2379
+ -- - `unsafe` calls MUST NOT be reentrant!
2380
+ -- This means it must be guaranteed that there exists no possible
2381
+ -- code path that can call back into Haskell.
2382
+ --
2383
+ -- Here is an example of the seemingly innocent function `PQisBusy()`
2384
+ -- actually being reentrant in some cases:
2385
+ -- `PQisBusy()` in some cases calls `pqParseInput3()`
2386
+ -- which calls `pqGetErrorNotice3()` which can call back into a
2387
+ -- user-defined error notice processing callback if set,
2388
+ -- which the user might have set to be a Haskell function.
2376
2389
2377
2390
foreign import ccall " libpq-fe.h PQconnectdb"
2378
2391
c_PQconnectdb :: CString -> IO (Ptr PGconn )
@@ -2383,51 +2396,66 @@ foreign import ccall "libpq-fe.h PQconnectStart"
2383
2396
foreign import ccall " libpq-fe.h PQconnectPoll"
2384
2397
c_PQconnectPoll :: Ptr PGconn -> IO CInt
2385
2398
2399
+ -- | `unsafe` is OK because `PQdb` calls no functions.
2386
2400
foreign import ccall unsafe " libpq-fe.h PQdb"
2387
2401
c_PQdb :: Ptr PGconn -> IO CString
2388
2402
2403
+ -- | `unsafe` is OK because `PQuser` calls no functions.
2389
2404
foreign import ccall unsafe " libpq-fe.h PQuser"
2390
2405
c_PQuser :: Ptr PGconn -> IO CString
2391
2406
2407
+ -- | `unsafe` is OK because `PQpass` calls no functions.
2392
2408
foreign import ccall unsafe " libpq-fe.h PQpass"
2393
2409
c_PQpass :: Ptr PGconn -> IO CString
2394
2410
2411
+ -- | `unsafe` is OK because `PQhost` calls no functions.
2395
2412
foreign import ccall unsafe " libpq-fe.h PQhost"
2396
2413
c_PQhost :: Ptr PGconn -> IO CString
2397
2414
2415
+ -- | `unsafe` is OK because `PQport` calls no functions.
2398
2416
foreign import ccall unsafe " libpq-fe.h PQport"
2399
2417
c_PQport :: Ptr PGconn -> IO CString
2400
2418
2419
+ -- | `unsafe` is OK because `PQport` calls no functions.
2401
2420
foreign import ccall unsafe " libpq-fe.h PQoptions"
2402
2421
c_PQoptions :: Ptr PGconn -> IO CString
2403
2422
2423
+ -- | `unsafe` is OK because `PQbackendPID` calls no functions.
2404
2424
foreign import ccall unsafe " libpq-fe.h PQbackendPID"
2405
2425
c_PQbackendPID :: Ptr PGconn -> IO CInt
2406
2426
2427
+ -- | `unsafe` is OK because `PQconnectionNeedsPassword` calls no functions
2428
+ -- (it calls `PQpass`, which does the same).
2407
2429
foreign import ccall unsafe " libpq-fe.h PQconnectionNeedsPassword"
2408
2430
c_PQconnectionNeedsPassword :: Ptr PGconn -> IO CInt
2409
2431
2432
+ -- | `unsafe` is OK because `PQconnectionUsedPassword` calls no functions.
2410
2433
foreign import ccall unsafe " libpq-fe.h PQconnectionUsedPassword"
2411
2434
c_PQconnectionUsedPassword :: Ptr PGconn -> IO CInt
2412
2435
2436
+ -- | `unsafe` is OK because `PQstatus` calls no functions.
2413
2437
foreign import ccall unsafe " libpq-fe.h PQstatus"
2414
2438
c_PQstatus :: Ptr PGconn -> IO CInt
2415
2439
2440
+ -- | `unsafe` is OK because `PQtransactionStatus` calls no functions.
2416
2441
foreign import ccall unsafe " libpq-fe.h PQtransactionStatus"
2417
2442
c_PQtransactionStatus :: Ptr PGconn -> IO CInt
2418
2443
2419
2444
foreign import ccall " libpq-fe.h PQparameterStatus"
2420
2445
c_PQparameterStatus :: Ptr PGconn -> CString -> IO CString
2421
2446
2447
+ -- | `unsafe` is OK because `PQprotocolVersion` calls no functions.
2422
2448
foreign import ccall unsafe " libpq-fe.h PQprotocolVersion"
2423
2449
c_PQprotocolVersion :: Ptr PGconn -> IO CInt
2424
2450
2451
+ -- | `unsafe` is OK because `PQserverVersion` calls no functions.
2425
2452
foreign import ccall unsafe " libpq-fe.h PQserverVersion"
2426
2453
c_PQserverVersion :: Ptr PGconn -> IO CInt
2427
2454
2428
2455
foreign import ccall " dynamic"
2429
2456
mkLibpqVersion :: FunPtr Int -> Int
2430
2457
2458
+ -- | `unsafe` is OK because `PQsocket` calls no functions.
2431
2459
foreign import ccall unsafe " libpq-fe.h PQsocket"
2432
2460
c_PQsocket :: Ptr PGconn -> IO CInt
2433
2461
@@ -2451,6 +2479,7 @@ foreign import ccall "libpq-fe.h PQresetStart"
2451
2479
foreign import ccall " libpq-fe.h PQresetPoll"
2452
2480
c_PQresetPoll :: Ptr PGconn -> IO CInt
2453
2481
2482
+ -- | `unsafe` is OK because `PQclientEncoding` calls no functions.
2454
2483
foreign import ccall unsafe " libpq-fe.h PQclientEncoding"
2455
2484
c_PQclientEncoding :: Ptr PGconn -> IO CInt
2456
2485
@@ -2461,6 +2490,7 @@ foreign import ccall "libpq-fe.h PQsetClientEncoding"
2461
2490
c_PQsetClientEncoding :: Ptr PGconn -> CString -> IO CInt
2462
2491
2463
2492
type PGVerbosity = CInt
2493
+ -- | `unsafe` is OK because `PQclientEncoding` calls no functions.
2464
2494
foreign import ccall unsafe " libpq-fe.h PQsetErrorVerbosity"
2465
2495
c_PQsetErrorVerbosity :: Ptr PGconn -> PGVerbosity -> IO PGVerbosity
2466
2496
@@ -2507,21 +2537,23 @@ foreign import ccall "libpq-fe.h &PQfreeCancel"
2507
2537
foreign import ccall " libpq-fe.h PQcancel"
2508
2538
c_PQcancel :: Ptr PGcancel -> CString -> CInt -> IO CInt
2509
2539
2510
- foreign import ccall unsafe " libpq-fe.h PQnotifies"
2540
+ foreign import ccall " libpq-fe.h PQnotifies"
2511
2541
c_PQnotifies :: Ptr PGconn -> IO (Ptr Notify )
2512
2542
2513
2543
foreign import ccall " libpq-fe.h PQconsumeInput"
2514
2544
c_PQconsumeInput :: Ptr PGconn -> IO CInt
2515
2545
2516
- foreign import ccall unsafe " libpq-fe.h PQisBusy"
2546
+ foreign import ccall " libpq-fe.h PQisBusy"
2517
2547
c_PQisBusy :: Ptr PGconn -> IO CInt
2518
2548
2519
2549
foreign import ccall " libpq-fe.h PQsetnonblocking"
2520
2550
c_PQsetnonblocking :: Ptr PGconn -> CInt -> IO CInt
2521
2551
2552
+ -- | `unsafe` is OK because `PQisnonblocking` calls only a macro that calls no functions.
2522
2553
foreign import ccall unsafe " libpq-fe.h PQisnonblocking"
2523
2554
c_PQisnonblocking :: Ptr PGconn -> IO CInt
2524
2555
2556
+ -- | `unsafe` is OK because `PQsetSingleRowMode` calls no functions.
2525
2557
foreign import ccall unsafe " libpq-fe.h PQsetSingleRowMode"
2526
2558
c_PQsetSingleRowMode :: Ptr PGconn -> IO CInt
2527
2559
@@ -2553,67 +2585,91 @@ foreign import ccall "libpq-fe.h PQdescribePortal"
2553
2585
foreign import ccall " libpq-fe.h &PQclear"
2554
2586
p_PQclear :: FunPtr (Ptr PGresult -> IO () )
2555
2587
2588
+ -- | `unsafe` is OK because `PQresultStatus` calls no functions.
2556
2589
foreign import ccall unsafe " libpq-fe.h PQresultStatus"
2557
2590
c_PQresultStatus :: Ptr PGresult -> IO CInt
2558
2591
2559
- foreign import ccall unsafe " libpq-fe.h PQresStatus"
2592
+ -- Must not be `unsafe` because `PQresStatus` may use `libpq_gettext()` that may do IO.
2593
+ foreign import ccall " libpq-fe.h PQresStatus"
2560
2594
c_PQresStatus :: CInt -> IO CString
2561
2595
2596
+ -- | `unsafe` is OK because `PQresultStatus` calls no functions.
2562
2597
foreign import ccall unsafe " libpq-fe.h PQresultErrorMessage"
2563
2598
c_PQresultErrorMessage :: Ptr PGresult -> IO CString
2564
2599
2565
2600
foreign import ccall " libpq-fe.h PQresultErrorField"
2566
2601
c_PQresultErrorField :: Ptr PGresult -> CInt -> IO CString
2567
2602
2603
+ -- | `unsafe` is OK because `PQntuples` calls no functions.
2568
2604
foreign import ccall unsafe " libpq-fe.h PQntuples"
2569
2605
c_PQntuples :: Ptr PGresult -> CInt
2570
2606
2607
+ -- | `unsafe` is OK because `PQnfields` calls no functions.
2571
2608
foreign import ccall unsafe " libpq-fe.h PQnfields"
2572
2609
c_PQnfields :: Ptr PGresult -> CInt
2573
2610
2574
- foreign import ccall unsafe " libpq-fe.h PQfname"
2611
+ -- Must not be `unsafe` because `PQfname` may call `check_field_number()` which may call `pqInternalNotice()`.
2612
+ foreign import ccall " libpq-fe.h PQfname"
2575
2613
c_PQfname :: Ptr PGresult -> CInt -> IO CString
2576
2614
2615
+ -- | `unsafe` is OK because `PQfnumber` calls only `pg_tolower()`, which calls
2616
+ -- only C stdlib functions that cannot be reentrant.
2617
+ -- Note `pg_tolower()` also calls `strdup()` and `free()`, so if one of those
2618
+ -- was overridden with e.g. glibc hooks to call back into Haskell, this would be wrong.
2619
+ -- However, these functions are generally considered to not be reentrant.
2577
2620
foreign import ccall unsafe " libpq-fe.h PQfnumber"
2578
2621
c_PQfnumber :: Ptr PGresult -> CString -> IO CInt
2579
2622
2580
- foreign import ccall unsafe " libpq-fe.h PQftable"
2623
+ -- Must not be `unsafe` because `PQftable` may call `check_field_number()` which may call `pqInternalNotice()`.
2624
+ foreign import ccall " libpq-fe.h PQftable"
2581
2625
c_PQftable :: Ptr PGresult -> CInt -> IO Oid
2582
2626
2583
- foreign import ccall unsafe " libpq-fe.h PQftablecol"
2627
+ -- Must not be `unsafe` because `PQftablecol` may call `check_field_number()` which may call `pqInternalNotice()`.
2628
+ foreign import ccall " libpq-fe.h PQftablecol"
2584
2629
c_PQftablecol :: Ptr PGresult -> CInt -> IO CInt
2585
2630
2586
- foreign import ccall unsafe " libpq-fe.h PQfformat"
2631
+ -- Must not be `unsafe` because `PQfformat` may call `check_field_number()` which may call `pqInternalNotice()`.
2632
+ foreign import ccall " libpq-fe.h PQfformat"
2587
2633
c_PQfformat :: Ptr PGresult -> CInt -> IO CInt
2588
2634
2635
+ -- Must not be `unsafe` because `PQftype` may call `check_field_number()` which may call `pqInternalNotice()`.
2589
2636
foreign import ccall unsafe " libpq-fe.h PQftype"
2590
2637
c_PQftype :: Ptr PGresult -> CInt -> IO Oid
2591
2638
2592
- foreign import ccall unsafe " libpq-fe.h PQfmod"
2639
+ -- Must not be `unsafe` because `PQfmod` may call `check_field_number()` which may call `pqInternalNotice()`.
2640
+ foreign import ccall " libpq-fe.h PQfmod"
2593
2641
c_PQfmod :: Ptr PGresult -> CInt -> IO CInt
2594
2642
2595
- foreign import ccall unsafe " libpq-fe.h PQfsize"
2643
+ -- Must not be `unsafe` because `PQfsize` may call `check_field_number()` which may call `pqInternalNotice()`.
2644
+ foreign import ccall " libpq-fe.h PQfsize"
2596
2645
c_PQfsize :: Ptr PGresult -> CInt -> IO CInt
2597
2646
2598
- foreign import ccall unsafe " libpq-fe.h PQgetvalue"
2647
+ -- Must not be `unsafe` because `PQgetvalue` may call `check_tuple_field_number()` which may call `pqInternalNotice()`.
2648
+ foreign import ccall " libpq-fe.h PQgetvalue"
2599
2649
c_PQgetvalue :: Ptr PGresult -> CInt -> CInt -> IO CString
2600
2650
2601
- foreign import ccall unsafe " libpq-fe.h PQgetisnull"
2651
+ -- Must not be `unsafe` because `PQgetisnull` may call `check_tuple_field_number()` which may call `pqInternalNotice()`.
2652
+ foreign import ccall " libpq-fe.h PQgetisnull"
2602
2653
c_PQgetisnull :: Ptr PGresult -> CInt -> CInt -> IO CInt
2603
2654
2604
- foreign import ccall unsafe " libpq-fe.h PQgetlength"
2655
+ -- Must not be `unsafe` because `PQgetlength` may call `check_tuple_field_number()` which may call `pqInternalNotice()`.
2656
+ foreign import ccall " libpq-fe.h PQgetlength"
2605
2657
c_PQgetlength :: Ptr PGresult -> CInt -> CInt -> IO CInt
2606
2658
2659
+ -- | `unsafe` is OK because `PQnparams` calls no functions.
2607
2660
foreign import ccall unsafe " libpq-fe.h PQnparams"
2608
2661
c_PQnparams :: Ptr PGresult -> IO CInt
2609
2662
2610
- foreign import ccall unsafe " libpq-fe.h PQparamtype"
2663
+ -- Must not be `unsafe` because `PQparamtype` may call `check_param_number()` which may call `pqInternalNotice()`.
2664
+ foreign import ccall " libpq-fe.h PQparamtype"
2611
2665
c_PQparamtype :: Ptr PGresult -> CInt -> IO Oid
2612
2666
2667
+ -- | `unsafe` is OK because `PQcmdStatus` calls no functions.
2613
2668
foreign import ccall unsafe " libpq-fe.h PQcmdStatus"
2614
2669
c_PQcmdStatus :: Ptr PGresult -> IO CString
2615
2670
2616
- foreign import ccall unsafe " libpq-fe.h PQcmdTuples"
2671
+ -- Must not be `unsafe` because `PQcmdTuples` may call `pqInternalNotice()`.
2672
+ foreign import ccall " libpq-fe.h PQcmdTuples"
2617
2673
c_PQcmdTuples :: Ptr PGresult -> IO CString
2618
2674
2619
2675
foreign import ccall " libpq-fe.h PQescapeStringConn"
@@ -2636,33 +2692,42 @@ foreign import ccall "libpq-fe.h PQunescapeBytea"
2636
2692
-> Ptr CSize
2637
2693
-> IO (Ptr Word8 ) -- Actually (IO (Ptr CUChar))
2638
2694
2639
- foreign import ccall unsafe " libpq-fe.h PQescapeIdentifier"
2695
+ -- Must not be `unsafe` because `PQescapeIdentifier` may call `libpq_gettext()` that may do IO.
2696
+ foreign import ccall " libpq-fe.h PQescapeIdentifier"
2640
2697
c_PQescapeIdentifier :: Ptr PGconn
2641
2698
-> CString
2642
2699
-> CSize
2643
2700
-> IO CString
2644
2701
2702
+ -- | `unsafe` is OK because `PQfreemem` only calls `free()`.
2645
2703
foreign import ccall unsafe " libpq-fe.h &PQfreemem"
2646
2704
p_PQfreemem :: FunPtr (Ptr a -> IO () )
2647
2705
2706
+ -- | `unsafe` is OK because `PQfreemem` only calls `free()`.
2648
2707
foreign import ccall unsafe " libpq-fe.h PQfreemem"
2649
2708
c_PQfreemem :: Ptr a -> IO ()
2650
2709
2710
+ -- | `unsafe` is OK because `hs_postgresql_libpq_malloc_noticebuffer` only calls `malloc()`.
2651
2711
foreign import ccall unsafe " noticehandlers.h hs_postgresql_libpq_malloc_noticebuffer"
2652
2712
c_malloc_noticebuffer :: IO (Ptr CNoticeBuffer )
2653
2713
2714
+ -- | `unsafe` is OK because `hs_postgresql_libpq_malloc_noticebuffer` only calls `free()`.
2654
2715
foreign import ccall unsafe " noticehandlers.h hs_postgresql_libpq_free_noticebuffer"
2655
2716
c_free_noticebuffer :: Ptr CNoticeBuffer -> IO ()
2656
2717
2718
+ -- | `unsafe` is OK because `hs_postgresql_libpq_get_notice` calls no functions.
2657
2719
foreign import ccall unsafe " noticehandlers.h hs_postgresql_libpq_get_notice"
2658
2720
c_get_notice :: Ptr CNoticeBuffer -> IO (Ptr PGnotice )
2659
2721
2722
+ -- | `unsafe` is OK because `hs_postgresql_libpq_discard_notices` calls no functions.
2660
2723
foreign import ccall unsafe " noticehandlers.h &hs_postgresql_libpq_discard_notices"
2661
2724
p_discard_notices :: FunPtr NoticeReceiver
2662
2725
2726
+ -- | `unsafe` is OK because `hs_postgresql_libpq_store_notices` calls only `PQresultErrorMessage`, which calls no functions.
2663
2727
foreign import ccall unsafe " noticehandlers.h &hs_postgresql_libpq_store_notices"
2664
2728
p_store_notices :: FunPtr NoticeReceiver
2665
2729
2730
+ -- | `unsafe` is OK because `PQsetNoticeReceiver` calls no functions.
2666
2731
foreign import ccall unsafe " libpq-fe.h PQsetNoticeReceiver"
2667
2732
c_PQsetNoticeReceiver :: Ptr PGconn -> FunPtr NoticeReceiver -> Ptr CNoticeBuffer -> IO (FunPtr NoticeReceiver )
2668
2733
0 commit comments