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

Commit6ed0599

Browse files
committed
Fix race condition in psql \e's detection of file modification.
psql's editing commands decide whether the user has edited the fileby checking for change of modification timestamp. This is probablyfine for a pre-existing file, but with a temporary file that iscreated within the command, it's possible for a fast typist tosave-and-exit in less than the one-second granularity of stat(2)timestamps. On Windows FAT filesystems the granularity is evenworse, 2 seconds, making the race a bit easier to hit.To fix, try to set the temp file's mod time to be two seconds ago.It's unlikely this would fail, but then again the race conditionitself is unlikely, so just ignore any error.Also, we might as well check the file size as well as its mod time.While this is a difficult bug to hit, it still seems worthback-patching, to ensure that users' edits aren't lost.Laurenz Albe, per gripe from Jacob Champion; based on fix suggestionsfrom Jacob and myselfDiscussion:https://postgr.es/m/0ba3f2a658bac6546d9934ab6ba63a805d46a49b.camel@cybertec.at
1 parent8a22977 commit6ed0599

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

‎src/bin/psql/command.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include<ctype.h>
1111
#include<time.h>
1212
#include<pwd.h>
13+
#include<utime.h>
1314
#ifndefWIN32
1415
#include<sys/stat.h>/* for stat() */
1516
#include<fcntl.h>/* open() flags */
@@ -3704,7 +3705,6 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
37043705
constchar*fname;
37053706
boolerror= false;
37063707
intfd;
3707-
37083708
structstatbefore,
37093709
after;
37103710

@@ -3729,13 +3729,13 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
37293729
!ret ?strerror(errno) :"");
37303730
return false;
37313731
}
3732+
#endif
37323733

37333734
/*
37343735
* No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
37353736
* current directory to the supplied path unless we use only
37363737
* backslashes, so we do that.
37373738
*/
3738-
#endif
37393739
#ifndefWIN32
37403740
snprintf(fnametmp,sizeof(fnametmp),"%s%spsql.edit.%d.sql",tmpdir,
37413741
"/", (int)getpid());
@@ -3785,6 +3785,24 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
37853785
pg_log_error("%s: %m",fname);
37863786
error= true;
37873787
}
3788+
else
3789+
{
3790+
structutimbufut;
3791+
3792+
/*
3793+
* Try to set the file modification time of the temporary file
3794+
* a few seconds in the past. Otherwise, the low granularity
3795+
* (one second, or even worse on some filesystems) that we can
3796+
* portably measure with stat(2) could lead us to not
3797+
* recognize a modification, if the user typed very quickly.
3798+
*
3799+
* This is a rather unlikely race condition, so don't error
3800+
* out if the utime(2) call fails --- that would make the cure
3801+
* worse than the disease.
3802+
*/
3803+
ut.modtime=ut.actime=time(NULL)-2;
3804+
(void)utime(fname,&ut);
3805+
}
37883806
}
37893807
}
37903808

@@ -3804,7 +3822,10 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
38043822
error= true;
38053823
}
38063824

3807-
if (!error&&before.st_mtime!=after.st_mtime)
3825+
/* file was edited if the size or modification time has changed */
3826+
if (!error&&
3827+
(before.st_size!=after.st_size||
3828+
before.st_mtime!=after.st_mtime))
38083829
{
38093830
stream=fopen(fname,PG_BINARY_R);
38103831
if (!stream)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp