40
40
* themselves, as there could pointers to them in active use. See
41
41
* smgrrelease() and smgrreleaseall().
42
42
*
43
+ * NB: We need to hold interrupts across most of the functions in this file,
44
+ * as otherwise interrupt processing, e.g. due to a < ERROR elog/ereport, can
45
+ * trigger procsignal processing, which in turn can trigger
46
+ * smgrreleaseall(). Most of the relevant code is not reentrant. It seems
47
+ * better to put the HOLD_INTERRUPTS()/RESUME_INTERRUPTS() here, instead of
48
+ * trying to push them down to md.c where possible: For one, every smgr
49
+ * implementation would be vulnerable, for another, a good bit of smgr.c code
50
+ * itself is affected too. Eventually we might want a more targeted solution,
51
+ * allowing e.g. a networked smgr implementation to be interrupted, but many
52
+ * other, more complicated, problems would need to be fixed for that to be
53
+ * viable (e.g. smgr.c is often called with interrupts already held).
54
+ *
43
55
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
44
56
* Portions Copyright (c) 1994, Regents of the University of California
45
57
*
53
65
54
66
#include "access/xlogutils.h"
55
67
#include "lib/ilist.h"
68
+ #include "miscadmin.h"
56
69
#include "storage/bufmgr.h"
57
70
#include "storage/ipc.h"
58
71
#include "storage/md.h"
@@ -158,12 +171,16 @@ smgrinit(void)
158
171
{
159
172
int i ;
160
173
174
+ HOLD_INTERRUPTS ();
175
+
161
176
for (i = 0 ; i < NSmgr ; i ++ )
162
177
{
163
178
if (smgrsw [i ].smgr_init )
164
179
smgrsw [i ].smgr_init ();
165
180
}
166
181
182
+ RESUME_INTERRUPTS ();
183
+
167
184
/* register the shutdown proc */
168
185
on_proc_exit (smgrshutdown , 0 );
169
186
}
@@ -176,11 +193,15 @@ smgrshutdown(int code, Datum arg)
176
193
{
177
194
int i ;
178
195
196
+ HOLD_INTERRUPTS ();
197
+
179
198
for (i = 0 ; i < NSmgr ; i ++ )
180
199
{
181
200
if (smgrsw [i ].smgr_shutdown )
182
201
smgrsw [i ].smgr_shutdown ();
183
202
}
203
+
204
+ RESUME_INTERRUPTS ();
184
205
}
185
206
186
207
/*
@@ -206,6 +227,8 @@ smgropen(RelFileLocator rlocator, ProcNumber backend)
206
227
207
228
Assert (RelFileNumberIsValid (rlocator .relNumber ));
208
229
230
+ HOLD_INTERRUPTS ();
231
+
209
232
if (SMgrRelationHash == NULL )
210
233
{
211
234
/* First time through: initialize the hash table */
@@ -242,6 +265,8 @@ smgropen(RelFileLocator rlocator, ProcNumber backend)
242
265
smgrsw [reln -> smgr_which ].smgr_open (reln );
243
266
}
244
267
268
+ RESUME_INTERRUPTS ();
269
+
245
270
return reln ;
246
271
}
247
272
@@ -283,6 +308,8 @@ smgrdestroy(SMgrRelation reln)
283
308
284
309
Assert (reln -> pincount == 0 );
285
310
311
+ HOLD_INTERRUPTS ();
312
+
286
313
for (forknum = 0 ; forknum <= MAX_FORKNUM ; forknum ++ )
287
314
smgrsw [reln -> smgr_which ].smgr_close (reln , forknum );
288
315
@@ -292,6 +319,8 @@ smgrdestroy(SMgrRelation reln)
292
319
& (reln -> smgr_rlocator ),
293
320
HASH_REMOVE , NULL ) == NULL )
294
321
elog (ERROR , "SMgrRelation hashtable corrupted" );
322
+
323
+ RESUME_INTERRUPTS ();
295
324
}
296
325
297
326
/*
@@ -302,12 +331,16 @@ smgrdestroy(SMgrRelation reln)
302
331
void
303
332
smgrrelease (SMgrRelation reln )
304
333
{
334
+ HOLD_INTERRUPTS ();
335
+
305
336
for (ForkNumber forknum = 0 ; forknum <= MAX_FORKNUM ; forknum ++ )
306
337
{
307
338
smgrsw [reln -> smgr_which ].smgr_close (reln , forknum );
308
339
reln -> smgr_cached_nblocks [forknum ] = InvalidBlockNumber ;
309
340
}
310
341
reln -> smgr_targblock = InvalidBlockNumber ;
342
+
343
+ RESUME_INTERRUPTS ();
311
344
}
312
345
313
346
/*
@@ -336,6 +369,9 @@ smgrdestroyall(void)
336
369
{
337
370
dlist_mutable_iter iter ;
338
371
372
+ /* seems unsafe to accept interrupts while in a dlist_foreach_modify() */
373
+ HOLD_INTERRUPTS ();
374
+
339
375
/*
340
376
* Zap all unpinned SMgrRelations. We rely on smgrdestroy() to remove
341
377
* each one from the list.
@@ -347,6 +383,8 @@ smgrdestroyall(void)
347
383
348
384
smgrdestroy (rel );
349
385
}
386
+
387
+ RESUME_INTERRUPTS ();
350
388
}
351
389
352
390
/*
@@ -362,12 +400,17 @@ smgrreleaseall(void)
362
400
if (SMgrRelationHash == NULL )
363
401
return ;
364
402
403
+ /* seems unsafe to accept interrupts while iterating */
404
+ HOLD_INTERRUPTS ();
405
+
365
406
hash_seq_init (& status , SMgrRelationHash );
366
407
367
408
while ((reln = (SMgrRelation ) hash_seq_search (& status )) != NULL )
368
409
{
369
410
smgrrelease (reln );
370
411
}
412
+
413
+ RESUME_INTERRUPTS ();
371
414
}
372
415
373
416
/*
@@ -400,7 +443,13 @@ smgrreleaserellocator(RelFileLocatorBackend rlocator)
400
443
bool
401
444
smgrexists (SMgrRelation reln , ForkNumber forknum )
402
445
{
403
- return smgrsw [reln -> smgr_which ].smgr_exists (reln , forknum );
446
+ bool ret ;
447
+
448
+ HOLD_INTERRUPTS ();
449
+ ret = smgrsw [reln -> smgr_which ].smgr_exists (reln , forknum );
450
+ RESUME_INTERRUPTS ();
451
+
452
+ return ret ;
404
453
}
405
454
406
455
/*
@@ -413,7 +462,9 @@ smgrexists(SMgrRelation reln, ForkNumber forknum)
413
462
void
414
463
smgrcreate (SMgrRelation reln , ForkNumber forknum , bool isRedo )
415
464
{
465
+ HOLD_INTERRUPTS ();
416
466
smgrsw [reln -> smgr_which ].smgr_create (reln , forknum , isRedo );
467
+ RESUME_INTERRUPTS ();
417
468
}
418
469
419
470
/*
@@ -436,6 +487,8 @@ smgrdosyncall(SMgrRelation *rels, int nrels)
436
487
437
488
FlushRelationsAllBuffers (rels , nrels );
438
489
490
+ HOLD_INTERRUPTS ();
491
+
439
492
/*
440
493
* Sync the physical file(s).
441
494
*/
@@ -449,6 +502,8 @@ smgrdosyncall(SMgrRelation *rels, int nrels)
449
502
smgrsw [which ].smgr_immedsync (rels [i ], forknum );
450
503
}
451
504
}
505
+
506
+ RESUME_INTERRUPTS ();
452
507
}
453
508
454
509
/*
@@ -471,6 +526,13 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
471
526
if (nrels == 0 )
472
527
return ;
473
528
529
+ /*
530
+ * It would be unsafe to process interrupts between DropRelationBuffers()
531
+ * and unlinking the underlying files. This probably should be a critical
532
+ * section, but we're not there yet.
533
+ */
534
+ HOLD_INTERRUPTS ();
535
+
474
536
/*
475
537
* Get rid of any remaining buffers for the relations. bufmgr will just
476
538
* drop them without bothering to write the contents.
@@ -522,6 +584,8 @@ smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
522
584
}
523
585
524
586
pfree (rlocators );
587
+
588
+ RESUME_INTERRUPTS ();
525
589
}
526
590
527
591
538
602
smgrextend (SMgrRelation reln , ForkNumber forknum , BlockNumber blocknum ,
539
603
const void * buffer , bool skipFsync )
540
604
{
605
+ HOLD_INTERRUPTS ();
606
+
541
607
smgrsw [reln -> smgr_which ].smgr_extend (reln , forknum , blocknum ,
542
608
buffer , skipFsync );
543
609
@@ -550,6 +616,8 @@ smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
550
616
reln -> smgr_cached_nblocks [forknum ] = blocknum + 1 ;
551
617
else
552
618
reln -> smgr_cached_nblocks [forknum ] = InvalidBlockNumber ;
619
+
620
+ RESUME_INTERRUPTS ();
553
621
}
554
622
555
623
/*
563
631
smgrzeroextend (SMgrRelation reln , ForkNumber forknum , BlockNumber blocknum ,
564
632
int nblocks , bool skipFsync )
565
633
{
634
+ HOLD_INTERRUPTS ();
635
+
566
636
smgrsw [reln -> smgr_which ].smgr_zeroextend (reln , forknum , blocknum ,
567
637
nblocks , skipFsync );
568
638
@@ -575,6 +645,8 @@ smgrzeroextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
575
645
reln -> smgr_cached_nblocks [forknum ] = blocknum + nblocks ;
576
646
else
577
647
reln -> smgr_cached_nblocks [forknum ] = InvalidBlockNumber ;
648
+
649
+ RESUME_INTERRUPTS ();
578
650
}
579
651
580
652
/*
@@ -588,7 +660,13 @@ bool
588
660
smgrprefetch (SMgrRelation reln , ForkNumber forknum , BlockNumber blocknum ,
589
661
int nblocks )
590
662
{
591
- return smgrsw [reln -> smgr_which ].smgr_prefetch (reln , forknum , blocknum , nblocks );
663
+ bool ret ;
664
+
665
+ HOLD_INTERRUPTS ();
666
+ ret = smgrsw [reln -> smgr_which ].smgr_prefetch (reln , forknum , blocknum , nblocks );
667
+ RESUME_INTERRUPTS ();
668
+
669
+ return ret ;
592
670
}
593
671
594
672
/*
@@ -601,7 +679,13 @@ uint32
601
679
smgrmaxcombine (SMgrRelation reln , ForkNumber forknum ,
602
680
BlockNumber blocknum )
603
681
{
604
- return smgrsw [reln -> smgr_which ].smgr_maxcombine (reln , forknum , blocknum );
682
+ uint32 ret ;
683
+
684
+ HOLD_INTERRUPTS ();
685
+ ret = smgrsw [reln -> smgr_which ].smgr_maxcombine (reln , forknum , blocknum );
686
+ RESUME_INTERRUPTS ();
687
+
688
+ return ret ;
605
689
}
606
690
607
691
/*
@@ -619,8 +703,10 @@ void
619
703
smgrreadv (SMgrRelation reln , ForkNumber forknum , BlockNumber blocknum ,
620
704
void * * buffers , BlockNumber nblocks )
621
705
{
706
+ HOLD_INTERRUPTS ();
622
707
smgrsw [reln -> smgr_which ].smgr_readv (reln , forknum , blocknum , buffers ,
623
708
nblocks );
709
+ RESUME_INTERRUPTS ();
624
710
}
625
711
626
712
/*
@@ -653,8 +739,10 @@ void
653
739
smgrwritev (SMgrRelation reln , ForkNumber forknum , BlockNumber blocknum ,
654
740
const void * * buffers , BlockNumber nblocks , bool skipFsync )
655
741
{
742
+ HOLD_INTERRUPTS ();
656
743
smgrsw [reln -> smgr_which ].smgr_writev (reln , forknum , blocknum ,
657
744
buffers , nblocks , skipFsync );
745
+ RESUME_INTERRUPTS ();
658
746
}
659
747
660
748
/*
@@ -665,8 +753,10 @@ void
665
753
smgrwriteback (SMgrRelation reln , ForkNumber forknum , BlockNumber blocknum ,
666
754
BlockNumber nblocks )
667
755
{
756
+ HOLD_INTERRUPTS ();
668
757
smgrsw [reln -> smgr_which ].smgr_writeback (reln , forknum , blocknum ,
669
758
nblocks );
759
+ RESUME_INTERRUPTS ();
670
760
}
671
761
672
762
/*
@@ -683,10 +773,14 @@ smgrnblocks(SMgrRelation reln, ForkNumber forknum)
683
773
if (result != InvalidBlockNumber )
684
774
return result ;
685
775
776
+ HOLD_INTERRUPTS ();
777
+
686
778
result = smgrsw [reln -> smgr_which ].smgr_nblocks (reln , forknum );
687
779
688
780
reln -> smgr_cached_nblocks [forknum ] = result ;
689
781
782
+ RESUME_INTERRUPTS ();
783
+
690
784
return result ;
691
785
}
692
786
@@ -784,7 +878,9 @@ smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks,
784
878
void
785
879
smgrregistersync (SMgrRelation reln , ForkNumber forknum )
786
880
{
881
+ HOLD_INTERRUPTS ();
787
882
smgrsw [reln -> smgr_which ].smgr_registersync (reln , forknum );
883
+ RESUME_INTERRUPTS ();
788
884
}
789
885
790
886
/*
@@ -816,7 +912,9 @@ smgrregistersync(SMgrRelation reln, ForkNumber forknum)
816
912
void
817
913
smgrimmedsync (SMgrRelation reln , ForkNumber forknum )
818
914
{
915
+ HOLD_INTERRUPTS ();
819
916
smgrsw [reln -> smgr_which ].smgr_immedsync (reln , forknum );
917
+ RESUME_INTERRUPTS ();
820
918
}
821
919
822
920
/*
0 commit comments