Bug 843857: Fix connection error handling in UnixSocket; r=tzimmermann

This commit is contained in:
Kyle Machulis 2014-01-24 12:06:40 -08:00
parent 0bb46c7685
commit 07eebca28f

View File

@ -174,6 +174,9 @@ public:
RefPtr<UnixSocketConsumer> mConsumer;
private:
void FireSocketError();
/**
* libevent triggered functions that reads data from socket when available and
* guarenteed non-blocking. Only to be called on IO thread.
@ -487,29 +490,47 @@ void ShutdownSocketTask::Run()
}
void
UnixSocketImpl::Accept()
UnixSocketImpl::FireSocketError()
{
MOZ_ASSERT(!NS_IsMainThread());
if (!mConnector) {
NS_WARNING("No connector object available!");
return;
}
// Clean up watchers, statuses, fds
mReadWatcher.StopWatchingFileDescriptor();
mWriteWatcher.StopWatchingFileDescriptor();
mConnectionStatus = SOCKET_DISCONNECTED;
mFd.reset(-1);
// Tell the main thread we've errored
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
}
void
UnixSocketImpl::Accept()
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(mConnector);
// This will set things we don't particularly care about, but it will hand
// back the correct structure size which is what we do care about.
if (!mConnector->CreateAddr(true, mAddrSize, mAddr, nullptr)) {
NS_WARNING("Cannot create socket address!");
FireSocketError();
return;
}
if (mFd.get() < 0) {
mFd = mConnector->Create();
if (mFd.get() < 0) {
NS_WARNING("Cannot create socket fd!");
FireSocketError();
return;
}
if (!SetSocketFlags()) {
NS_WARNING("Cannot set socket flags!");
FireSocketError();
return;
}
@ -517,6 +538,7 @@ UnixSocketImpl::Accept()
#ifdef DEBUG
CHROMIUM_LOG("...bind(%d) gave errno %d", mFd.get(), errno);
#endif
FireSocketError();
return;
}
@ -524,15 +546,13 @@ UnixSocketImpl::Accept()
#ifdef DEBUG
CHROMIUM_LOG("...listen(%d) gave errno %d", mFd.get(), errno);
#endif
FireSocketError();
return;
}
if (!mConnector->SetUpListenSocket(mFd)) {
NS_WARNING("Could not set up listen socket!");
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
mConnectionStatus = SOCKET_DISCONNECTED;
FireSocketError();
return;
}
@ -545,15 +565,13 @@ void
UnixSocketImpl::Connect()
{
MOZ_ASSERT(!NS_IsMainThread());
if (!mConnector) {
NS_WARNING("No connector object available!");
return;
}
MOZ_ASSERT(mConnector);
if (mFd.get() < 0) {
mFd = mConnector->Create();
if (mFd.get() < 0) {
NS_WARNING("Cannot create socket fd!");
FireSocketError();
return;
}
}
@ -562,15 +580,14 @@ UnixSocketImpl::Connect()
if (!mConnector->CreateAddr(false, mAddrSize, mAddr, mAddress.get())) {
NS_WARNING("Cannot create socket address!");
FireSocketError();
return;
}
// Select non-blocking IO.
if (-1 == fcntl(mFd.get(), F_SETFL, O_NONBLOCK)) {
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
mConnectionStatus = SOCKET_DISCONNECTED;
NS_WARNING("Cannot set nonblock!");
FireSocketError();
return;
}
@ -583,20 +600,12 @@ UnixSocketImpl::Connect()
int current_opts = fcntl(mFd.get(), F_GETFL, 0);
if (-1 == current_opts) {
NS_WARNING("Cannot get socket opts!");
mFd.reset(-1);
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
mConnectionStatus = SOCKET_DISCONNECTED;
FireSocketError();
return;
}
if (-1 == fcntl(mFd.get(), F_SETFL, current_opts & ~O_NONBLOCK)) {
NS_WARNING("Cannot set socket opts to blocking!");
mFd.reset(-1);
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
mConnectionStatus = SOCKET_DISCONNECTED;
FireSocketError();
return;
}
@ -616,20 +625,19 @@ UnixSocketImpl::Connect()
#if DEBUG
CHROMIUM_LOG("Socket connect errno=%d\n", errno);
#endif
mFd.reset(-1);
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
mConnectionStatus = SOCKET_DISCONNECTED;
FireSocketError();
return;
}
if (!SetSocketFlags()) {
NS_WARNING("Cannot set socket flags!");
FireSocketError();
return;
}
if (!mConnector->SetUp(mFd)) {
NS_WARNING("Could not set up socket!");
FireSocketError();
return;
}
@ -862,30 +870,19 @@ UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
if (ret || error) {
NS_WARNING("getsockopt failure on async socket connect!");
mFd.reset(-1);
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
mConnectionStatus = SOCKET_DISCONNECTED;
FireSocketError();
return;
}
if (!SetSocketFlags()) {
mFd.reset(-1);
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
mConnectionStatus = SOCKET_DISCONNECTED;
NS_WARNING("Cannot set socket flags!");
FireSocketError();
return;
}
if (!mConnector->SetUp(mFd)) {
NS_WARNING("Could not set up socket!");
mFd.reset(-1);
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
mConnectionStatus = SOCKET_DISCONNECTED;
FireSocketError();
return;
}