Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f07f6b6

Browse files
committed
Avoid depending on non-POSIX behavior of fcntl(2).
The POSIX standard does not say that the success return value for fcntl(F_SETFD) and fcntl(F_SETFL) is zero; it says only that it's not -1. We had several calls that were making the stronger assumption. Adjust them to test specifically for -1 for strict spec compliance. The standard further leaves open the possibility that the O_NONBLOCK flag bit is not the only active one in F_SETFL's argument. Formally, therefore, one ought to get the current flags with F_GETFL and store them back with only the O_NONBLOCK bit changed when trying to change the nonblock state. In port/noblock.c, we were doing the full pushup in pg_set_block but not in pg_set_noblock, which is just weird. Make both of them do it properly, since they have little business making any assumptions about the socket they're handed. The other places where we're issuing F_SETFL are working with FDs we just got from pipe(2), so it's reasonable to assume the FDs' properties are all default, so I didn't bother adding F_GETFL steps there. Also, while pg_set_block deserves some points for trying to do things right, somebody had decided that it'd be even better to cast fcntl's third argument to "long". Which is completely loony, because POSIX clearly says the third argument for an F_SETFL call is "int". Given the lack of field complaints, these missteps apparently are not of significance on any common platforms. But they're still wrong, so back-patch to all supported branches. Discussion: https://postgr.es/m/30882.1492800880@sss.pgh.pa.us
1 parent 6c73b39 commit f07f6b6

File tree

4 files changed

+25
-8
lines changed

4 files changed

+25
-8
lines changed

src/backend/postmaster/postmaster.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -6214,7 +6214,7 @@ InitPostmasterDeathWatchHandle(void)
62146214
* write fd. That is taken care of in ClosePostmasterPorts().
62156215
*/
62166216
Assert(MyProcPid == PostmasterPid);
6217-
if (pipe(postmaster_alive_fds))
6217+
if (pipe(postmaster_alive_fds) < 0)
62186218
ereport(FATAL,
62196219
(errcode_for_file_access(),
62206220
errmsg_internal("could not create pipe to monitor postmaster death: %m")));
@@ -6223,7 +6223,7 @@ InitPostmasterDeathWatchHandle(void)
62236223
* Set O_NONBLOCK to allow testing for the fd's presence with a read()
62246224
* call.
62256225
*/
6226-
if (fcntl(postmaster_alive_fds[POSTMASTER_FD_WATCH], F_SETFL, O_NONBLOCK))
6226+
if (fcntl(postmaster_alive_fds[POSTMASTER_FD_WATCH], F_SETFL, O_NONBLOCK) == -1)
62276227
ereport(FATAL,
62286228
(errcode_for_socket_access(),
62296229
errmsg_internal("could not set postmaster death monitoring pipe to nonblocking mode: %m")));

src/backend/storage/ipc/latch.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ InitializeLatchSupport(void)
169169
*/
170170
if (pipe(pipefd) < 0)
171171
elog(FATAL, "pipe() failed: %m");
172-
if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) < 0)
172+
if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) == -1)
173173
elog(FATAL, "fcntl() failed on read-end of self-pipe: %m");
174-
if (fcntl(pipefd[1], F_SETFL, O_NONBLOCK) < 0)
174+
if (fcntl(pipefd[1], F_SETFL, O_NONBLOCK) == -1)
175175
elog(FATAL, "fcntl() failed on write-end of self-pipe: %m");
176176

177177
selfpipe_readfd = pipefd[0];

src/bin/pg_test_fsync/pg_test_fsync.c

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <sys/stat.h>
99
#include <sys/time.h>
10+
#include <fcntl.h>
1011
#include <time.h>
1112
#include <unistd.h>
1213
#include <signal.h>

src/port/noblock.c

+20-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*-------------------------------------------------------------------------
22
*
33
* noblock.c
4-
* set a file descriptor as non-blocking
4+
* set a file descriptor as blocking or non-blocking
55
*
66
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
@@ -17,11 +17,22 @@
1717
#include <fcntl.h>
1818

1919

20+
/*
21+
* Put socket into nonblock mode.
22+
* Returns true on success, false on failure.
23+
*/
2024
bool
2125
pg_set_noblock(pgsocket sock)
2226
{
2327
#if !defined(WIN32)
24-
return (fcntl(sock, F_SETFL, O_NONBLOCK) != -1);
28+
int flags;
29+
30+
flags = fcntl(sock, F_GETFL);
31+
if (flags < 0)
32+
return false;
33+
if (fcntl(sock, F_SETFL, (flags | O_NONBLOCK)) == -1)
34+
return false;
35+
return true;
2536
#else
2637
unsigned long ioctlsocket_ret = 1;
2738

@@ -30,15 +41,20 @@ pg_set_noblock(pgsocket sock)
3041
#endif
3142
}
3243

33-
44+
/*
45+
* Put socket into blocking mode.
46+
* Returns true on success, false on failure.
47+
*/
3448
bool
3549
pg_set_block(pgsocket sock)
3650
{
3751
#if !defined(WIN32)
3852
int flags;
3953

4054
flags = fcntl(sock, F_GETFL);
41-
if (flags < 0 || fcntl(sock, F_SETFL, (long) (flags & ~O_NONBLOCK)))
55+
if (flags < 0)
56+
return false;
57+
if (fcntl(sock, F_SETFL, (flags & ~O_NONBLOCK)) == -1)
4258
return false;
4359
return true;
4460
#else

0 commit comments

Comments
 (0)