Bug 977672: Assert O_NONBLOCK for watched file descriptors, r=kyle

We cannot use blocking file-descriptor I/O on the I/O thread. This
patch adds an assertion to UnixFdWatcher the tests for the O_NONBLOCK
flag, when installing a file descriptor. In UnixFileWatcher, the
Open method tests for the O_NONBLOCK flag for the opened file.

File-descriptor flags for UnixSocketImpl et al are currently set by
UnixSocketImpl itself. Later patches should move this into the
methods of connector classes.
This commit is contained in:
Thomas Zimmermann
2014-02-28 10:16:52 +01:00
parent ad1f76355b
commit 57168bdf14
5 changed files with 40 additions and 35 deletions

View File

@@ -124,13 +124,6 @@ public:
*/
void Listen();
/**
* Set up flags on whatever our current file descriptor is.
*
* @return true if successful, false otherwise
*/
bool SetSocketFlags(int aFd);
void GetSocketAddr(nsAString& aAddrStr)
{
if (!mConnector) {
@@ -156,6 +149,8 @@ public:
void OnSocketCanSendWithoutBlocking() MOZ_OVERRIDE;
private:
// Set up flags on whatever our current file descriptor is.
static bool SetSocketFlags(int aFd);
void FireSocketError();
@@ -464,13 +459,12 @@ UnixSocketImpl::Listen()
FireSocketError();
return;
}
SetFd(fd);
if (!SetSocketFlags(GetFd())) {
if (!SetSocketFlags(fd)) {
NS_WARNING("Cannot set socket flags!");
FireSocketError();
return;
}
SetFd(fd);
// calls OnListening on success, or OnError otherwise
nsresult rv = UnixSocketWatcher::Listen(
@@ -492,6 +486,11 @@ UnixSocketImpl::Connect()
FireSocketError();
return;
}
if (!SetSocketFlags(fd)) {
NS_WARNING("Cannot set socket flags!");
FireSocketError();
return;
}
SetFd(fd);
}
@@ -512,16 +511,27 @@ UnixSocketImpl::SetSocketFlags(int aFd)
{
// Set socket addr to be reused even if kernel is still waiting to close
int n = 1;
setsockopt(aFd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
// Set close-on-exec bit.
int flags = fcntl(aFd, F_GETFD);
if (-1 == flags) {
if (setsockopt(aFd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) < 0) {
return false;
}
// Set close-on-exec bit.
int flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFD));
if (-1 == flags) {
return false;
}
flags |= FD_CLOEXEC;
if (-1 == fcntl(aFd, F_SETFD, flags)) {
if (-1 == TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFD, flags))) {
return false;
}
// Set non-blocking status flag.
flags = TEMP_FAILURE_RETRY(fcntl(aFd, F_GETFL));
if (-1 == flags) {
return false;
}
flags |= O_NONBLOCK;
if (-1 == TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, flags))) {
return false;
}
@@ -541,10 +551,10 @@ UnixSocketImpl::OnAccepted(int aFd)
RemoveWatchers(READ_WATCHER|WRITE_WATCHER);
Close();
SetSocket(aFd, SOCKET_IS_CONNECTED);
if (!SetSocketFlags(GetFd())) {
if (!SetSocketFlags(aFd)) {
return;
}
SetSocket(aFd, SOCKET_IS_CONNECTED);
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS);