mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1240122 - threadsafe fix for getselfaddr() r=dragana
This commit is contained in:
parent
b9942da1dd
commit
96ab3c52d0
@ -744,6 +744,7 @@ nsSocketTransport::nsSocketTransport()
|
|||||||
, mOutputClosed(true)
|
, mOutputClosed(true)
|
||||||
, mResolving(false)
|
, mResolving(false)
|
||||||
, mNetAddrIsSet(false)
|
, mNetAddrIsSet(false)
|
||||||
|
, mSelfAddrIsSet(false)
|
||||||
, mLock("nsSocketTransport.mLock")
|
, mLock("nsSocketTransport.mLock")
|
||||||
, mFD(this)
|
, mFD(this)
|
||||||
, mFDref(0)
|
, mFDref(0)
|
||||||
@ -910,6 +911,7 @@ nsSocketTransport::InitWithFilename(const char *filename)
|
|||||||
nsresult
|
nsresult
|
||||||
nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const NetAddr *addr)
|
nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const NetAddr *addr)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "wrong thread");
|
||||||
NS_ASSERTION(!mFD.IsInitialized(), "already initialized");
|
NS_ASSERTION(!mFD.IsInitialized(), "already initialized");
|
||||||
|
|
||||||
char buf[kNetAddrMaxCStrBufSize];
|
char buf[kNetAddrMaxCStrBufSize];
|
||||||
@ -930,6 +932,7 @@ nsSocketTransport::InitWithConnectedSocket(PRFileDesc *fd, const NetAddr *addr)
|
|||||||
mPollFlags = (PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT);
|
mPollFlags = (PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT);
|
||||||
mPollTimeout = mTimeouts[TIMEOUT_READ_WRITE];
|
mPollTimeout = mTimeouts[TIMEOUT_READ_WRITE];
|
||||||
mState = STATE_TRANSFERRING;
|
mState = STATE_TRANSFERRING;
|
||||||
|
SetSocketName(fd);
|
||||||
mNetAddrIsSet = true;
|
mNetAddrIsSet = true;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -1649,13 +1652,14 @@ nsSocketTransport::OnMsgOutputClosed(nsresult reason)
|
|||||||
void
|
void
|
||||||
nsSocketTransport::OnSocketConnected()
|
nsSocketTransport::OnSocketConnected()
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "wrong thread");
|
||||||
SOCKET_LOG((" advancing to STATE_TRANSFERRING\n"));
|
SOCKET_LOG((" advancing to STATE_TRANSFERRING\n"));
|
||||||
|
|
||||||
mPollFlags = (PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT);
|
mPollFlags = (PR_POLL_READ | PR_POLL_WRITE | PR_POLL_EXCEPT);
|
||||||
mPollTimeout = mTimeouts[TIMEOUT_READ_WRITE];
|
mPollTimeout = mTimeouts[TIMEOUT_READ_WRITE];
|
||||||
mState = STATE_TRANSFERRING;
|
mState = STATE_TRANSFERRING;
|
||||||
|
|
||||||
// Set the mNetAddrIsSet flag only when state has reached TRANSFERRING
|
// Set the m*AddrIsSet flags only when state has reached TRANSFERRING
|
||||||
// because we need to make sure its value does not change due to failover
|
// because we need to make sure its value does not change due to failover
|
||||||
mNetAddrIsSet = true;
|
mNetAddrIsSet = true;
|
||||||
|
|
||||||
@ -1665,6 +1669,7 @@ nsSocketTransport::OnSocketConnected()
|
|||||||
MutexAutoLock lock(mLock);
|
MutexAutoLock lock(mLock);
|
||||||
NS_ASSERTION(mFD.IsInitialized(), "no socket");
|
NS_ASSERTION(mFD.IsInitialized(), "no socket");
|
||||||
NS_ASSERTION(mFDref == 1, "wrong socket ref count");
|
NS_ASSERTION(mFDref == 1, "wrong socket ref count");
|
||||||
|
SetSocketName(mFD);
|
||||||
mFDconnected = true;
|
mFDconnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1679,6 +1684,22 @@ nsSocketTransport::OnSocketConnected()
|
|||||||
SendStatus(NS_NET_STATUS_CONNECTED_TO);
|
SendStatus(NS_NET_STATUS_CONNECTED_TO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsSocketTransport::SetSocketName(PRFileDesc *fd)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread, "wrong thread");
|
||||||
|
if (mSelfAddrIsSet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRNetAddr prAddr;
|
||||||
|
memset(&prAddr, 0, sizeof(prAddr));
|
||||||
|
if (PR_GetSockName(fd, &prAddr) == PR_SUCCESS) {
|
||||||
|
PRNetAddrToNetAddr(&prAddr, &mSelfAddr);
|
||||||
|
mSelfAddrIsSet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PRFileDesc *
|
PRFileDesc *
|
||||||
nsSocketTransport::GetFD_Locked()
|
nsSocketTransport::GetFD_Locked()
|
||||||
{
|
{
|
||||||
@ -2325,31 +2346,19 @@ nsSocketTransport::GetPeerAddr(NetAddr *addr)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsSocketTransport::GetSelfAddr(NetAddr *addr)
|
nsSocketTransport::GetSelfAddr(NetAddr *addr)
|
||||||
{
|
{
|
||||||
// we must not call any PR methods on our file descriptor
|
// once we are in the connected state, mSelfAddr will not change.
|
||||||
// while holding mLock since those methods might re-enter
|
// so if we can verify that we are in the connected state, then
|
||||||
// socket transport code.
|
// we can freely access mSelfAddr from any thread without being
|
||||||
|
// inside a critical section.
|
||||||
|
|
||||||
PRFileDescAutoLock fd(this);
|
if (!mSelfAddrIsSet) {
|
||||||
if (!fd.IsInitialized()) {
|
SOCKET_LOG(("nsSocketTransport::GetSelfAddr [this=%p state=%d] "
|
||||||
return NS_ERROR_NOT_CONNECTED;
|
"NOT_AVAILABLE because not yet connected.", this, mState));
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRNetAddr prAddr;
|
memcpy(addr, &mSelfAddr, sizeof(NetAddr));
|
||||||
|
return NS_OK;
|
||||||
// NSPR doesn't tell us the socket address's length (as provided by
|
|
||||||
// the 'getsockname' system call), so we can't distinguish between
|
|
||||||
// named, unnamed, and abstract Unix domain socket names. (Server
|
|
||||||
// sockets are never unnamed, obviously, but client sockets can use
|
|
||||||
// any kind of address.) Clear prAddr first, so that the path for
|
|
||||||
// unnamed and abstract addresses will at least be reliably empty,
|
|
||||||
// and not garbage for unnamed sockets.
|
|
||||||
memset(&prAddr, 0, sizeof(prAddr));
|
|
||||||
|
|
||||||
nsresult rv =
|
|
||||||
(PR_GetSockName(fd, &prAddr) == PR_SUCCESS) ? NS_OK : NS_ERROR_FAILURE;
|
|
||||||
PRNetAddrToNetAddr(&prAddr, addr);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -319,10 +319,13 @@ private:
|
|||||||
nsCOMPtr<nsICancelable> mDNSRequest;
|
nsCOMPtr<nsICancelable> mDNSRequest;
|
||||||
nsCOMPtr<nsIDNSRecord> mDNSRecord;
|
nsCOMPtr<nsIDNSRecord> mDNSRecord;
|
||||||
|
|
||||||
// mNetAddr is valid from GetPeerAddr() once we have
|
// mNetAddr/mSelfAddr is valid from GetPeerAddr()/GetSelfAddr() once we have
|
||||||
// reached STATE_TRANSFERRING. It must not change after that.
|
// reached STATE_TRANSFERRING. It must not change after that.
|
||||||
|
void SetSocketName(PRFileDesc *fd);
|
||||||
mozilla::net::NetAddr mNetAddr;
|
mozilla::net::NetAddr mNetAddr;
|
||||||
bool mNetAddrIsSet;
|
mozilla::net::NetAddr mSelfAddr; // getsockname()
|
||||||
|
mozilla::Atomic<bool, mozilla::Relaxed> mNetAddrIsSet;
|
||||||
|
mozilla::Atomic<bool, mozilla::Relaxed> mSelfAddrIsSet;
|
||||||
|
|
||||||
nsAutoPtr<mozilla::net::NetAddr> mBindAddr;
|
nsAutoPtr<mozilla::net::NetAddr> mBindAddr;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user