Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit7a57a67

Browse files
committed
Replace opendir/closedir calls throughout the backend with AllocateDir
and FreeDir routines modeled on the existing AllocateFile/FreeFile.Like the latter, these routines will avoid failing on EMFILE/ENFILEconditions whenever possible, and will prevent leakage of directorydescriptors if an elog() occurs while one is open.Also, reduce PANIC to ERROR in MoveOfflineLogs() --- this is notcritical code and there is no reason to force a DB restart on failure.All per recent trouble report from Olivier Hubaut.
1 parent4f57131 commit7a57a67

File tree

6 files changed

+138
-41
lines changed

6 files changed

+138
-41
lines changed

‎contrib/dbsize/dbsize.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
#include"postgres.h"
22

33
#include<sys/types.h>
4-
#include<dirent.h>
54
#include<sys/stat.h>
65
#include<unistd.h>
7-
#include<errno.h>
86

97
#include"access/heapam.h"
108
#include"catalog/catalog.h"
119
#include"catalog/namespace.h"
1210
#include"commands/dbcommands.h"
1311
#include"fmgr.h"
12+
#include"storage/fd.h"
1413
#include"utils/builtins.h"
1514

1615

@@ -58,7 +57,7 @@ database_size(PG_FUNCTION_ARGS)
5857

5958
dbpath=GetDatabasePath(dbid);
6059

61-
dirdesc=opendir(dbpath);
60+
dirdesc=AllocateDir(dbpath);
6261
if (!dirdesc)
6362
ereport(ERROR,
6463
(errcode_for_file_access(),
@@ -93,7 +92,7 @@ database_size(PG_FUNCTION_ARGS)
9392
pfree(fullname);
9493
}
9594

96-
closedir(dirdesc);
95+
FreeDir(dirdesc);
9796

9897
PG_RETURN_INT64(totalsize);
9998
}

‎src/backend/access/transam/slru.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@
66
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.12 2004/02/1703:45:17 momjian Exp $
9+
* $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.13 2004/02/23 23:03:10 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
1313
#include"postgres.h"
1414

1515
#include<fcntl.h>
16-
#include<dirent.h>
17-
#include<errno.h>
1816
#include<sys/stat.h>
1917
#include<unistd.h>
2018

@@ -888,7 +886,7 @@ SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions)
888886
intsegpage;
889887
charpath[MAXPGPATH];
890888

891-
cldir=opendir(ctl->Dir);
889+
cldir=AllocateDir(ctl->Dir);
892890
if (cldir==NULL)
893891
ereport(ERROR,
894892
(errcode_for_file_access(),
@@ -927,7 +925,7 @@ SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions)
927925
ereport(ERROR,
928926
(errcode_for_file_access(),
929927
errmsg("could not read directory \"%s\": %m",ctl->Dir)));
930-
closedir(cldir);
928+
FreeDir(cldir);
931929

932930
returnfound;
933931
}

‎src/backend/access/transam/xlog.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.136 2004/02/1703:45:17 momjian Exp $
10+
* $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.137 2004/02/23 23:03:10 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -17,10 +17,8 @@
1717
#include<fcntl.h>
1818
#include<signal.h>
1919
#include<unistd.h>
20-
#include<errno.h>
2120
#include<sys/stat.h>
2221
#include<sys/time.h>
23-
#include<dirent.h>
2422

2523
#include"access/clog.h"
2624
#include"access/transam.h"
@@ -1753,9 +1751,9 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr)
17531751

17541752
XLByteToPrevSeg(endptr,endlogId,endlogSeg);
17551753

1756-
xldir=opendir(XLogDir);
1754+
xldir=AllocateDir(XLogDir);
17571755
if (xldir==NULL)
1758-
ereport(PANIC,
1756+
ereport(ERROR,
17591757
(errcode_for_file_access(),
17601758
errmsg("could not open transaction log directory \"%s\": %m",
17611759
XLogDir)));
@@ -1812,11 +1810,11 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr)
18121810
errno=0;
18131811
#endif
18141812
if (errno)
1815-
ereport(PANIC,
1813+
ereport(ERROR,
18161814
(errcode_for_file_access(),
18171815
errmsg("could not read transaction log directory \"%s\": %m",
18181816
XLogDir)));
1819-
closedir(xldir);
1817+
FreeDir(xldir);
18201818
}
18211819

18221820
/*

‎src/backend/storage/file/fd.c

Lines changed: 109 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.107 2004/02/2320:45:59 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.108 2004/02/2323:03:10 tgl Exp $
1111
*
1212
* NOTES:
1313
*
@@ -43,8 +43,6 @@
4343
#include<sys/file.h>
4444
#include<sys/param.h>
4545
#include<sys/stat.h>
46-
#include<dirent.h>
47-
#include<errno.h>
4846
#include<unistd.h>
4947
#include<fcntl.h>
5048

@@ -87,11 +85,11 @@ intmax_files_per_process = 1000;
8785

8886
/*
8987
* Maximum number of file descriptors to open for either VFD entries or
90-
* AllocateFile files. This is initialized to a conservative value, and
91-
* remains that way indefinitely in bootstrap or standalone-backend cases.
92-
* In normal postmaster operation, the postmaster calls set_max_safe_fds()
93-
* late in initialization to update the value, and that value is then
94-
* inherited by forked subprocesses.
88+
* AllocateFile/AllocateDir operations. This is initialized to a conservative
89+
*value, andremains that way indefinitely in bootstrap or standalone-backend
90+
*cases.In normal postmaster operation, the postmaster calls
91+
*set_max_safe_fds()late in initialization to update the value, and that
92+
*value is theninherited by forked subprocesses.
9593
*
9694
* Note: the value of max_files_per_process is taken into account while
9795
* setting this variable, and so need not be tested separately.
@@ -159,6 +157,17 @@ static intnfile = 0;
159157
staticintnumAllocatedFiles=0;
160158
staticFILE*allocatedFiles[MAX_ALLOCATED_FILES];
161159

160+
/*
161+
* List of <dirent.h> DIRs opened with AllocateDir.
162+
*
163+
* Since we don't have heavy use of AllocateDir, it seems OK to put a pretty
164+
* small maximum limit on the number of simultaneously allocated dirs.
165+
*/
166+
#defineMAX_ALLOCATED_DIRS 10
167+
168+
staticintnumAllocatedDirs=0;
169+
staticDIR*allocatedDirs[MAX_ALLOCATED_DIRS];
170+
162171
/*
163172
* Number of temporary files opened during the current session;
164173
* this is used in generation of tempfile names.
@@ -489,7 +498,7 @@ LruInsert(File file)
489498

490499
if (FileIsNotOpen(file))
491500
{
492-
while (nfile+numAllocatedFiles >=max_safe_fds)
501+
while (nfile+numAllocatedFiles+numAllocatedDirs>=max_safe_fds)
493502
{
494503
if (!ReleaseLruFile())
495504
break;
@@ -748,7 +757,7 @@ fileNameOpenFile(FileName fileName,
748757
file=AllocateVfd();
749758
vfdP=&VfdCache[file];
750759

751-
while (nfile+numAllocatedFiles >=max_safe_fds)
760+
while (nfile+numAllocatedFiles+numAllocatedDirs>=max_safe_fds)
752761
{
753762
if (!ReleaseLruFile())
754763
break;
@@ -1099,8 +1108,8 @@ AllocateFile(char *name, char *mode)
10991108
* looping.
11001109
*/
11011110
if (numAllocatedFiles >=MAX_ALLOCATED_FILES||
1102-
numAllocatedFiles >=max_safe_fds-1)
1103-
elog(ERROR,"too many privateFDs demanded");
1111+
numAllocatedFiles+numAllocatedDirs>=max_safe_fds-1)
1112+
elog(ERROR,"too many privatefiles demanded");
11041113

11051114
TryAgain:
11061115
if ((file=fopen(name,mode))!=NULL)
@@ -1155,6 +1164,86 @@ FreeFile(FILE *file)
11551164
returnfclose(file);
11561165
}
11571166

1167+
1168+
/*
1169+
* Routines that want to use <dirent.h> (ie, DIR*) should use AllocateDir
1170+
* rather than plain opendir(). This lets fd.c deal with freeing FDs if
1171+
* necessary to open the directory, and with closing it after an elog.
1172+
* When done, call FreeDir rather than closedir.
1173+
*
1174+
* Ideally this should be the *only* direct call of opendir() in the backend.
1175+
*/
1176+
DIR*
1177+
AllocateDir(constchar*dirname)
1178+
{
1179+
DIR*dir;
1180+
1181+
DO_DB(elog(LOG,"AllocateDir: Allocated %d",numAllocatedDirs));
1182+
1183+
/*
1184+
* The test against MAX_ALLOCATED_DIRS prevents us from overflowing
1185+
* allocatedDirs[]; the test against max_safe_fds prevents AllocateDir
1186+
* from hogging every one of the available FDs, which'd lead to infinite
1187+
* looping.
1188+
*/
1189+
if (numAllocatedDirs >=MAX_ALLOCATED_DIRS||
1190+
numAllocatedDirs+numAllocatedFiles >=max_safe_fds-1)
1191+
elog(ERROR,"too many private dirs demanded");
1192+
1193+
TryAgain:
1194+
if ((dir=opendir(dirname))!=NULL)
1195+
{
1196+
allocatedDirs[numAllocatedDirs]=dir;
1197+
numAllocatedDirs++;
1198+
returndir;
1199+
}
1200+
1201+
if (errno==EMFILE||errno==ENFILE)
1202+
{
1203+
intsave_errno=errno;
1204+
1205+
ereport(LOG,
1206+
(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
1207+
errmsg("out of file descriptors: %m; release and retry")));
1208+
errno=0;
1209+
if (ReleaseLruFile())
1210+
gotoTryAgain;
1211+
errno=save_errno;
1212+
}
1213+
1214+
returnNULL;
1215+
}
1216+
1217+
/*
1218+
* Close a directory opened with AllocateDir.
1219+
*
1220+
* Note we do not check closedir's return value --- it is up to the caller
1221+
* to handle close errors.
1222+
*/
1223+
int
1224+
FreeDir(DIR*dir)
1225+
{
1226+
inti;
1227+
1228+
DO_DB(elog(LOG,"FreeDir: Allocated %d",numAllocatedDirs));
1229+
1230+
/* Remove dir from list of allocated dirs, if it's present */
1231+
for (i=numAllocatedDirs;--i >=0;)
1232+
{
1233+
if (allocatedDirs[i]==dir)
1234+
{
1235+
numAllocatedDirs--;
1236+
allocatedDirs[i]=allocatedDirs[numAllocatedDirs];
1237+
break;
1238+
}
1239+
}
1240+
if (i<0)
1241+
elog(WARNING,"dir passed to FreeDir was not obtained from AllocateDir");
1242+
1243+
returnclosedir(dir);
1244+
}
1245+
1246+
11581247
/*
11591248
* closeAllVfds
11601249
*
@@ -1211,7 +1300,7 @@ AtProcExit_Files(int code, Datum arg)
12111300
* exiting. If that's the case, we should remove all temporary files; if
12121301
* that's not the case, we are being called for transaction commit/abort
12131302
* and should only remove transaction-local temp files. In either case,
1214-
* also clean up "allocated" stdio files.
1303+
* also clean up "allocated" stdio files and dirs.
12151304
*/
12161305
staticvoid
12171306
CleanupTempFiles(boolisProcExit)
@@ -1240,6 +1329,9 @@ CleanupTempFiles(bool isProcExit)
12401329

12411330
while (numAllocatedFiles>0)
12421331
FreeFile(allocatedFiles[0]);
1332+
1333+
while (numAllocatedDirs>0)
1334+
FreeDir(allocatedDirs[0]);
12431335
}
12441336

12451337

@@ -1271,7 +1363,7 @@ RemovePgTempFiles(void)
12711363
* files.
12721364
*/
12731365
snprintf(db_path,sizeof(db_path),"%s/base",DataDir);
1274-
if ((db_dir=opendir(db_path))!=NULL)
1366+
if ((db_dir=AllocateDir(db_path))!=NULL)
12751367
{
12761368
while ((db_de=readdir(db_dir))!=NULL)
12771369
{
@@ -1287,7 +1379,7 @@ RemovePgTempFiles(void)
12871379
"%s/%s/%s",
12881380
db_path,db_de->d_name,
12891381
PG_TEMP_FILES_DIR);
1290-
if ((temp_dir=opendir(temp_path))!=NULL)
1382+
if ((temp_dir=AllocateDir(temp_path))!=NULL)
12911383
{
12921384
while ((temp_de=readdir(temp_dir))!=NULL)
12931385
{
@@ -1310,9 +1402,9 @@ RemovePgTempFiles(void)
13101402
"unexpected file found in temporary-files directory: \"%s\"",
13111403
rm_path);
13121404
}
1313-
closedir(temp_dir);
1405+
FreeDir(temp_dir);
13141406
}
13151407
}
1316-
closedir(db_dir);
1408+
FreeDir(db_dir);
13171409
}
13181410
}

‎src/include/storage/fd.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/storage/fd.h,v 1.43 2004/02/2320:45:59 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/storage/fd.h,v 1.44 2004/02/2323:03:10 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -31,10 +31,16 @@
3131
* use FreeFile, not fclose, to close it. AVOID using stdio for files
3232
* that you intend to hold open for any length of time, since there is
3333
* no way for them to share kernel file descriptors with other files.
34+
*
35+
* Likewise, use AllocateDir/FreeDir, not opendir/closedir, to allocate
36+
* open directories (DIR*).
3437
*/
3538
#ifndefFD_H
3639
#defineFD_H
3740

41+
#include<dirent.h>
42+
43+
3844
/*
3945
* FileSeek uses the standard UNIX lseek(2) flags.
4046
*/
@@ -65,7 +71,11 @@ extern intFileTruncate(File file, long offset);
6571

6672
/* Operations that allow use of regular stdio --- USE WITH CAUTION */
6773
externFILE*AllocateFile(char*name,char*mode);
68-
externintFreeFile(FILE*);
74+
externintFreeFile(FILE*file);
75+
76+
/* Operations to allow use of the <dirent.h> library routines */
77+
externDIR*AllocateDir(constchar*dirname);
78+
externintFreeDir(DIR*dir);
6979

7080
/* If you've really really gotta have a plain kernel FD, use this */
7181
externintBasicOpenFile(FileNamefileName,intfileFlags,intfileMode);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp