Add more error handling for close() calls.

This commit is contained in:
Jon Siwek 2012-07-26 12:40:12 -05:00
parent d872b1d9f6
commit 734e5f68d3
7 changed files with 47 additions and 19 deletions

View file

@ -76,7 +76,7 @@ void ChunkedIO::DumpDebugData(const char* basefnname, bool want_reads)
ChunkedIOFd io(fd, "dump-file"); ChunkedIOFd io(fd, "dump-file");
io.Write(*i); io.Write(*i);
io.Flush(); io.Flush();
close(fd); safe_close(fd);
} }
l->clear(); l->clear();
@ -127,7 +127,7 @@ ChunkedIOFd::~ChunkedIOFd()
delete [] read_buffer; delete [] read_buffer;
delete [] write_buffer; delete [] write_buffer;
close(fd); safe_close(fd);
if ( partial ) if ( partial )
{ {
@ -686,7 +686,7 @@ ChunkedIOSSL::~ChunkedIOSSL()
ssl = 0; ssl = 0;
} }
close(socket); safe_close(socket);
} }

View file

@ -58,7 +58,7 @@ void FlowSrc::Process()
void FlowSrc::Close() void FlowSrc::Close()
{ {
close(selectable_fd); safe_close(selectable_fd);
} }

View file

@ -647,7 +647,7 @@ void RemoteSerializer::Fork()
exit(1); // FIXME: Better way to handle this? exit(1); // FIXME: Better way to handle this?
} }
close(pipe[1]); safe_close(pipe[1]);
return; return;
} }
@ -664,12 +664,12 @@ void RemoteSerializer::Fork()
} }
child.SetParentIO(io); child.SetParentIO(io);
close(pipe[0]); safe_close(pipe[0]);
// Close file descriptors. // Close file descriptors.
close(0); safe_close(0);
close(1); safe_close(1);
close(2); safe_close(2);
// Be nice. // Be nice.
setpriority(PRIO_PROCESS, 0, 5); setpriority(PRIO_PROCESS, 0, 5);
@ -4001,7 +4001,7 @@ bool SocketComm::Connect(Peer* peer)
if ( connect(sockfd, res->ai_addr, res->ai_addrlen) < 0 ) if ( connect(sockfd, res->ai_addr, res->ai_addrlen) < 0 )
{ {
Error(fmt("connect failed: %s", strerror(errno)), peer); Error(fmt("connect failed: %s", strerror(errno)), peer);
close(sockfd); safe_close(sockfd);
sockfd = -1; sockfd = -1;
continue; continue;
} }
@ -4174,16 +4174,18 @@ bool SocketComm::Listen()
{ {
Error(fmt("can't bind to %s:%s, %s", l_addr_str.c_str(), Error(fmt("can't bind to %s:%s, %s", l_addr_str.c_str(),
port_str, strerror(errno))); port_str, strerror(errno)));
close(fd);
if ( errno == EADDRINUSE ) if ( errno == EADDRINUSE )
{ {
// Abandon completely this attempt to set up listening sockets, // Abandon completely this attempt to set up listening sockets,
// try again later. // try again later.
safe_close(fd);
CloseListenFDs(); CloseListenFDs();
listen_next_try = time(0) + bind_retry_interval; listen_next_try = time(0) + bind_retry_interval;
return false; return false;
} }
safe_close(fd);
continue; continue;
} }
@ -4191,7 +4193,7 @@ bool SocketComm::Listen()
{ {
Error(fmt("can't listen on %s:%s, %s", l_addr_str.c_str(), Error(fmt("can't listen on %s:%s, %s", l_addr_str.c_str(),
port_str, strerror(errno))); port_str, strerror(errno)));
close(fd); safe_close(fd);
continue; continue;
} }
@ -4227,7 +4229,7 @@ bool SocketComm::AcceptConnection(int fd)
{ {
Error(fmt("accept fail, unknown address family %d", Error(fmt("accept fail, unknown address family %d",
client.ss.ss_family)); client.ss.ss_family));
close(clientfd); safe_close(clientfd);
return false; return false;
} }
@ -4298,7 +4300,7 @@ const char* SocketComm::MakeLogString(const char* msg, Peer* peer)
void SocketComm::CloseListenFDs() void SocketComm::CloseListenFDs()
{ {
for ( size_t i = 0; i < listen_fds.size(); ++i ) for ( size_t i = 0; i < listen_fds.size(); ++i )
close(listen_fds[i]); safe_close(listen_fds[i]);
listen_fds.clear(); listen_fds.clear();
} }

View file

@ -746,7 +746,7 @@ FileSerializer::~FileSerializer()
if ( io ) if ( io )
delete io; // destructor will call close() on fd delete io; // destructor will call close() on fd
else if ( fd >= 0 ) else if ( fd >= 0 )
close(fd); safe_close(fd);
} }
bool FileSerializer::Open(const char* file, bool pure) bool FileSerializer::Open(const char* file, bool pure)
@ -810,7 +810,7 @@ void FileSerializer::CloseFile()
io->Flush(); io->Flush();
if ( fd >= 0 && ! io ) // destructor of io calls close() on fd if ( fd >= 0 && ! io ) // destructor of io calls close() on fd
close(fd); safe_close(fd);
fd = -1; fd = -1;
delete [] file; delete [] file;

View file

@ -86,7 +86,7 @@ void Ascii::CloseFile(double t)
WriteHeaderField("end", ts); WriteHeaderField("end", ts);
} }
close(fd); safe_close(fd);
fd = 0; fd = 0;
} }

View file

@ -722,7 +722,7 @@ void init_random_seed(uint32 seed, const char* read_file, const char* write_file
{ {
int amt = read(fd, buf + pos, int amt = read(fd, buf + pos,
sizeof(uint32) * (bufsiz - pos)); sizeof(uint32) * (bufsiz - pos));
close(fd); safe_close(fd);
if ( amt > 0 ) if ( amt > 0 )
pos += amt / sizeof(uint32); pos += amt / sizeof(uint32);
@ -1204,7 +1204,7 @@ void _set_processing_status(const char* status)
len -= n; len -= n;
} }
close(fd); safe_close(fd);
errno = old_errno; errno = old_errno;
} }
@ -1353,6 +1353,29 @@ bool safe_write(int fd, const char* data, int len)
return true; return true;
} }
void safe_close(int fd)
{
/*
* Failure cases of close(2) are ...
* EBADF: Indicative of programming logic error that needs to be fixed, we
* should always be attempting to close a valid file descriptor.
* EINTR: Ignore signal interruptions, most implementations will actually
* reclaim the open descriptor and POSIX standard doesn't leave many
* options by declaring the state of the descriptor as "unspecified".
* Attempting to inspect actual state or re-attempt close() is not
* thread safe.
* EIO: Again the state of descriptor is "unspecified", but don't recover
* from an I/O error, safe_write() won't either.
*/
if ( close(fd) < 0 && errno != EINTR )
{
char buf[128];
strerror_r(errno, buf, sizeof(buf));
fprintf(stderr, "safe_close error %d: %s\n", errno, buf);
abort();
}
}
void out_of_memory(const char* where) void out_of_memory(const char* where)
{ {
reporter->FatalError("out of memory in %s.\n", where); reporter->FatalError("out of memory in %s.\n", where);

View file

@ -297,6 +297,9 @@ inline size_t pad_size(size_t size)
// thread-safe as long as no two threads write to the same descriptor. // thread-safe as long as no two threads write to the same descriptor.
extern bool safe_write(int fd, const char* data, int len); extern bool safe_write(int fd, const char* data, int len);
// Wraps close(2) to emit error messages and abort on unrecoverable errors.
extern void safe_close(int fd);
extern void out_of_memory(const char* where); extern void out_of_memory(const char* where);
inline void* safe_realloc(void* ptr, size_t size) inline void* safe_realloc(void* ptr, size_t size)