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

Commite109e43

Browse files
committed
Fix unlink() for STATUS_DELETE_PENDING on Windows.
Commitf357233 assumed that it was OK to return ENOENT directly iflstat() failed that way. If we got STATUS_DELETE_PENDING while tryingto unlink a file that we had already unlinked successfully once beforebut someone else still had open (on a kernel version that has "pending"unlinks by default), then we would no longer reach the retry loop inpgunlink(). That loop claims to be only for handling sharing violations(a different phenomenon), but the errno is the same.Restore that behavior with an explicit check, to see if it fixes theoccasional 'directory not empty' failures seen in the pg_upgrade testson CI. Further improvements are possible with proposed upgrades tomodern Windows APIs that would replace this convoluted code.Reported-by: Justin Pryzby <pryzby@telsasoft.com>Reviewed-by: Michael Paquier <michael@paquier.xyz>Discussion:https://postgr.es/m/20220920013122.GA31833%40telsasoft.comDiscussion:https://postgr.es/m/CA%2BhUKG%2BajSQ_8eu2AogTncOnZ5me2D-Cn66iN_-wZnRjLN%2Bicg%40mail.gmail.com
1 parent4517358 commite109e43

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

‎src/port/dirmod.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
#endif
4040
#endif
4141

42+
#if defined(WIN32)&& !defined(__CYGWIN__)
43+
#include"port/win32ntdll.h"
44+
#endif
45+
4246
#if defined(WIN32)|| defined(__CYGWIN__)
4347

4448
/*
@@ -91,13 +95,30 @@ pgrename(const char *from, const char *to)
9195
return0;
9296
}
9397

98+
/*
99+
* Check if _pglstat64()'s reason for failure was STATUS_DELETE_PENDING.
100+
* This doesn't apply to Cygwin, which has its own lstat() that would report
101+
* the case as EACCES.
102+
*/
103+
staticbool
104+
lstat_error_was_status_delete_pending(void)
105+
{
106+
if (errno!=ENOENT)
107+
return false;
108+
#if defined(WIN32)&& !defined(__CYGWIN__)
109+
if (pg_RtlGetLastNtStatus()==STATUS_DELETE_PENDING)
110+
return true;
111+
#endif
112+
return false;
113+
}
94114

95115
/*
96116
*pgunlink
97117
*/
98118
int
99119
pgunlink(constchar*path)
100120
{
121+
boolis_lnk;
101122
intloops=0;
102123
structstatst;
103124

@@ -122,9 +143,22 @@ pgunlink(const char *path)
122143
* due to sharing violations, but that seems unlikely. We could perhaps
123144
* prevent that by holding a file handle ourselves across the lstat() and
124145
* the retry loop, but that seems like over-engineering for now.
146+
*
147+
* In the special case of a STATUS_DELETE_PENDING error (file already
148+
* unlinked, but someone still has it open), we don't want to report ENOENT
149+
* to the caller immediately, because rmdir(parent) would probably fail.
150+
* We want to wait until the file truly goes away so that simple recursive
151+
* directory unlink algorithms work.
125152
*/
126153
if (lstat(path,&st)<0)
127-
return-1;
154+
{
155+
if (lstat_error_was_status_delete_pending())
156+
is_lnk= false;
157+
else
158+
return-1;
159+
}
160+
else
161+
is_lnk=S_ISLNK(st.st_mode);
128162

129163
/*
130164
* We need to loop because even though PostgreSQL uses flags that allow
@@ -133,7 +167,7 @@ pgunlink(const char *path)
133167
* someone else to close the file, as the caller might be holding locks
134168
* and blocking other backends.
135169
*/
136-
while ((S_ISLNK(st.st_mode) ?rmdir(path) :unlink(path))<0)
170+
while ((is_lnk ?rmdir(path) :unlink(path))<0)
137171
{
138172
if (errno!=EACCES)
139173
return-1;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp