Bug 854846 - Make UnixSocket's connect function non-block. r=tzimmermann, a=leo+

This commit is contained in:
Kyle Machulis 2013-05-14 11:26:18 -04:00
Родитель 733a1cd2f3
Коммит d5aa94f2bc
1 изменённых файлов: 103 добавлений и 34 удалений

Просмотреть файл

@ -553,9 +553,49 @@ UnixSocketImpl::Connect()
return;
}
// Select non-blocking IO.
if (!SetNonblockFlags()) {
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
return;
}
ret = connect(mFd.get(), (struct sockaddr*)&mAddr, mAddrSize);
if (ret) {
if (errno == EINPROGRESS) {
// Select blocking IO again, since we've now at least queue'd the connect
// as nonblock.
int current_opts = fcntl(mFd.get(), F_GETFL, 0);
if (-1 == current_opts) {
NS_WARNING("Cannot get socket opts!");
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
return;
}
if (-1 == fcntl(mFd.get(), F_SETFL, current_opts & ~O_NONBLOCK)) {
NS_WARNING("Cannot set socket opts to blocking!");
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
return;
}
// Set up a write watch to make sure we receive the connect signal
MessageLoopForIO::current()->WatchFileDescriptor(
mFd.get(),
false,
MessageLoopForIO::WATCH_WRITE,
&mWriteWatcher,
this);
#ifdef DEBUG
LOG("UnixSocket Connection delayed!");
#endif
return;
}
#if DEBUG
LOG("Socket connect errno=%d\n", errno);
#endif
@ -716,6 +756,8 @@ UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
{
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(!mShuttingDownOnIOThread);
SocketConnectionStatus status = mConsumer->GetConnectionStatus();
if (status == SOCKET_CONNECTED) {
// Try to write the bytes of mCurrentRilRawData. If all were written, continue.
//
@ -757,6 +799,33 @@ UnixSocketImpl::OnFileCanWriteWithoutBlocking(int aFd)
mOutgoingQ.RemoveElementAt(0);
delete data;
}
} else if (status == SOCKET_CONNECTING) {
int error, ret;
socklen_t len = sizeof(error);
ret = getsockopt(mFd.get(), SOL_SOCKET, SO_ERROR, &error, &len);
if (ret || error) {
NS_WARNING("getsockopt failure on async socket connect!");
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
return;
}
if (!mConnector->SetUp(mFd)) {
NS_WARNING("Could not set up socket!");
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_ERROR);
NS_DispatchToMainThread(t);
return;
}
nsRefPtr<OnSocketEventTask> t =
new OnSocketEventTask(this, OnSocketEventTask::CONNECT_SUCCESS);
NS_DispatchToMainThread(t);
SetUpIO();
}
}
void