mirror of
https://github.com/samba-team/samba.git
synced 2025-02-14 01:57:53 +03:00
lib/tsocket: check for errors indicated by poll() before getsockopt(fd, SOL_SOCKET, SO_ERROR)
This also returns an error if we got TCP_FIN from the peer, which is only reported by an explicit POLLRDHUP check. Also on FreeBSD getsockopt(fd, SOL_SOCKET, SO_ERROR) fetches and resets the error, so a 2nd call no longer returns an error. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15202 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Ralph Boehme <slow@samba.org> (cherry picked from commit 29a65da63d730ecead1e7d4a81a76dd1c8c179ea)
This commit is contained in:
parent
8a4ef3d92e
commit
5c051d3806
@ -24,8 +24,10 @@
|
||||
#include "replace.h"
|
||||
#include "system/filesys.h"
|
||||
#include "system/network.h"
|
||||
#include "system/select.h"
|
||||
#include "tsocket.h"
|
||||
#include "tsocket_internal.h"
|
||||
#include "lib/util/select.h"
|
||||
#include "lib/util/iov_buf.h"
|
||||
#include "lib/util/blocking.h"
|
||||
#include "lib/util/util_net.h"
|
||||
@ -171,7 +173,42 @@ static ssize_t tsocket_bsd_netlink_pending(int fd)
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t tsocket_bsd_error(int fd)
|
||||
static int tsocket_bsd_poll_error(int fd)
|
||||
{
|
||||
struct pollfd pfd = {
|
||||
.fd = fd,
|
||||
#ifdef POLLRDHUP
|
||||
.events = POLLRDHUP, /* POLLERR and POLLHUP are not needed */
|
||||
#endif
|
||||
};
|
||||
int ret;
|
||||
|
||||
errno = 0;
|
||||
ret = sys_poll_intr(&pfd, 1, 0);
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (ret != 1) {
|
||||
return POLLNVAL;
|
||||
}
|
||||
|
||||
if (pfd.revents & POLLERR) {
|
||||
return POLLERR;
|
||||
}
|
||||
if (pfd.revents & POLLHUP) {
|
||||
return POLLHUP;
|
||||
}
|
||||
#ifdef POLLRDHUP
|
||||
if (pfd.revents & POLLRDHUP) {
|
||||
return POLLRDHUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* should never be reached! */
|
||||
return POLLNVAL;
|
||||
}
|
||||
|
||||
static int tsocket_bsd_sock_error(int fd)
|
||||
{
|
||||
int ret, error = 0;
|
||||
socklen_t len = sizeof(error);
|
||||
@ -192,6 +229,47 @@ static ssize_t tsocket_bsd_error(int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tsocket_bsd_error(int fd)
|
||||
{
|
||||
int ret;
|
||||
int poll_error = 0;
|
||||
|
||||
poll_error = tsocket_bsd_poll_error(fd);
|
||||
if (poll_error == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef POLLRDHUP
|
||||
if (poll_error == POLLRDHUP) {
|
||||
errno = ECONNRESET;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (poll_error == POLLHUP) {
|
||||
errno = EPIPE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* POLLERR and POLLNVAL fallback to
|
||||
* getsockopt(fd, SOL_SOCKET, SO_ERROR)
|
||||
* and force EPIPE as fallback.
|
||||
*/
|
||||
|
||||
errno = 0;
|
||||
ret = tsocket_bsd_sock_error(fd);
|
||||
if (ret == 0) {
|
||||
errno = EPIPE;
|
||||
}
|
||||
|
||||
if (errno == 0) {
|
||||
errno = EPIPE;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static ssize_t tsocket_bsd_pending(int fd)
|
||||
{
|
||||
int ret;
|
||||
|
Loading…
x
Reference in New Issue
Block a user