зеркало из https://github.com/mozilla/pjs.git
Bug 556214, part 3: IPC code wants to be using non-reentrant Monitor. r=bent
This commit is contained in:
Родитель
6a87d2af28
Коммит
240e3f8d9e
|
@ -45,7 +45,7 @@
|
||||||
#include "nsTraceRefcnt.h"
|
#include "nsTraceRefcnt.h"
|
||||||
#include "nsXULAppAPI.h"
|
#include "nsXULAppAPI.h"
|
||||||
|
|
||||||
using mozilla::MutexAutoLock;
|
using mozilla::MonitorAutoLock;
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct RunnableMethodTraits<mozilla::ipc::AsyncChannel>
|
struct RunnableMethodTraits<mozilla::ipc::AsyncChannel>
|
||||||
|
@ -106,8 +106,7 @@ AsyncChannel::AsyncChannel(AsyncListener* aListener)
|
||||||
: mTransport(0),
|
: mTransport(0),
|
||||||
mListener(aListener),
|
mListener(aListener),
|
||||||
mChannelState(ChannelClosed),
|
mChannelState(ChannelClosed),
|
||||||
mMutex("mozilla.ipc.AsyncChannel.mMutex"),
|
mMonitor("mozilla.ipc.AsyncChannel.mMonitor"),
|
||||||
mCvar(mMutex, "mozilla.ipc.AsyncChannel.mCvar"),
|
|
||||||
mIOLoop(),
|
mIOLoop(),
|
||||||
mWorkerLoop(),
|
mWorkerLoop(),
|
||||||
mChild(false),
|
mChild(false),
|
||||||
|
@ -155,7 +154,7 @@ AsyncChannel::Open(Transport* aTransport, MessageLoop* aIOLoop)
|
||||||
NS_ASSERTION(mWorkerLoop, "need a worker loop");
|
NS_ASSERTION(mWorkerLoop, "need a worker loop");
|
||||||
|
|
||||||
if (needOpen) { // child process
|
if (needOpen) { // child process
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
mIOLoop->PostTask(FROM_HERE,
|
mIOLoop->PostTask(FROM_HERE,
|
||||||
NewRunnableMethod(this,
|
NewRunnableMethod(this,
|
||||||
|
@ -163,7 +162,7 @@ AsyncChannel::Open(Transport* aTransport, MessageLoop* aIOLoop)
|
||||||
|
|
||||||
// FIXME/cjones: handle errors
|
// FIXME/cjones: handle errors
|
||||||
while (mChannelState != ChannelConnected) {
|
while (mChannelState != ChannelConnected) {
|
||||||
mCvar.Wait();
|
mMonitor.Wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +175,7 @@ AsyncChannel::Close()
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (ChannelError == mChannelState ||
|
if (ChannelError == mChannelState ||
|
||||||
ChannelTimeout == mChannelState) {
|
ChannelTimeout == mChannelState) {
|
||||||
|
@ -186,7 +185,7 @@ AsyncChannel::Close()
|
||||||
// also be deleted and the listener will never be notified
|
// also be deleted and the listener will never be notified
|
||||||
// of the channel error.
|
// of the channel error.
|
||||||
if (mListener) {
|
if (mListener) {
|
||||||
MutexAutoUnlock unlock(mMutex);
|
MonitorAutoUnlock unlock(mMonitor);
|
||||||
NotifyMaybeChannelError();
|
NotifyMaybeChannelError();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -212,24 +211,24 @@ void
|
||||||
AsyncChannel::SynchronouslyClose()
|
AsyncChannel::SynchronouslyClose()
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
mIOLoop->PostTask(
|
mIOLoop->PostTask(
|
||||||
FROM_HERE, NewRunnableMethod(this, &AsyncChannel::OnCloseChannel));
|
FROM_HERE, NewRunnableMethod(this, &AsyncChannel::OnCloseChannel));
|
||||||
|
|
||||||
while (ChannelClosed != mChannelState)
|
while (ChannelClosed != mChannelState)
|
||||||
mCvar.Wait();
|
mMonitor.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AsyncChannel::Send(Message* msg)
|
AsyncChannel::Send(Message* msg)
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertNotCurrentThreadOwns();
|
mMonitor.AssertNotCurrentThreadOwns();
|
||||||
NS_ABORT_IF_FALSE(MSG_ROUTING_NONE != msg->routing_id(), "need a route");
|
NS_ABORT_IF_FALSE(MSG_ROUTING_NONE != msg->routing_id(), "need a route");
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (!Connected()) {
|
if (!Connected()) {
|
||||||
ReportConnectionError("AsyncChannel");
|
ReportConnectionError("AsyncChannel");
|
||||||
|
@ -289,14 +288,14 @@ void
|
||||||
AsyncChannel::OnNotifyMaybeChannelError()
|
AsyncChannel::OnNotifyMaybeChannelError()
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertNotCurrentThreadOwns();
|
mMonitor.AssertNotCurrentThreadOwns();
|
||||||
|
|
||||||
// OnChannelError holds mMutex when it posts this task and this
|
// OnChannelError holds mMonitor when it posts this task and this
|
||||||
// task cannot be allowed to run until OnChannelError has
|
// task cannot be allowed to run until OnChannelError has
|
||||||
// exited. We enforce that order by grabbing the mutex here which
|
// exited. We enforce that order by grabbing the mutex here which
|
||||||
// should only continue once OnChannelError has completed.
|
// should only continue once OnChannelError has completed.
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +313,7 @@ AsyncChannel::OnNotifyMaybeChannelError()
|
||||||
void
|
void
|
||||||
AsyncChannel::NotifyChannelClosed()
|
AsyncChannel::NotifyChannelClosed()
|
||||||
{
|
{
|
||||||
mMutex.AssertNotCurrentThreadOwns();
|
mMonitor.AssertNotCurrentThreadOwns();
|
||||||
|
|
||||||
if (ChannelClosed != mChannelState)
|
if (ChannelClosed != mChannelState)
|
||||||
NS_RUNTIMEABORT("channel should have been closed!");
|
NS_RUNTIMEABORT("channel should have been closed!");
|
||||||
|
@ -329,7 +328,7 @@ AsyncChannel::NotifyChannelClosed()
|
||||||
void
|
void
|
||||||
AsyncChannel::NotifyMaybeChannelError()
|
AsyncChannel::NotifyMaybeChannelError()
|
||||||
{
|
{
|
||||||
mMutex.AssertNotCurrentThreadOwns();
|
mMonitor.AssertNotCurrentThreadOwns();
|
||||||
|
|
||||||
// TODO sort out Close() on this side racing with Close() on the
|
// TODO sort out Close() on this side racing with Close() on the
|
||||||
// other side
|
// other side
|
||||||
|
@ -456,7 +455,7 @@ AsyncChannel::OnMessageReceived(const Message& msg)
|
||||||
AssertIOThread();
|
AssertIOThread();
|
||||||
NS_ASSERTION(mChannelState != ChannelError, "Shouldn't get here!");
|
NS_ASSERTION(mChannelState != ChannelError, "Shouldn't get here!");
|
||||||
|
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (!MaybeInterceptSpecialIOMessage(msg))
|
if (!MaybeInterceptSpecialIOMessage(msg))
|
||||||
// wake up the worker, there's work to do
|
// wake up the worker, there's work to do
|
||||||
|
@ -470,7 +469,7 @@ AsyncChannel::OnChannelOpened()
|
||||||
{
|
{
|
||||||
AssertIOThread();
|
AssertIOThread();
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
mChannelState = ChannelOpening;
|
mChannelState = ChannelOpening;
|
||||||
}
|
}
|
||||||
/*assert*/mTransport->Connect();
|
/*assert*/mTransport->Connect();
|
||||||
|
@ -490,9 +489,9 @@ AsyncChannel::OnChannelConnected(int32 peer_pid)
|
||||||
AssertIOThread();
|
AssertIOThread();
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
mChannelState = ChannelConnected;
|
mChannelState = ChannelConnected;
|
||||||
mCvar.Notify();
|
mMonitor.Notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mExistingListener)
|
if(mExistingListener)
|
||||||
|
@ -508,7 +507,7 @@ AsyncChannel::OnChannelError()
|
||||||
{
|
{
|
||||||
AssertIOThread();
|
AssertIOThread();
|
||||||
|
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (ChannelClosing != mChannelState)
|
if (ChannelClosing != mChannelState)
|
||||||
mChannelState = ChannelError;
|
mChannelState = ChannelError;
|
||||||
|
@ -520,7 +519,7 @@ void
|
||||||
AsyncChannel::PostErrorNotifyTask()
|
AsyncChannel::PostErrorNotifyTask()
|
||||||
{
|
{
|
||||||
AssertIOThread();
|
AssertIOThread();
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
NS_ASSERTION(!mChannelErrorTask, "OnChannelError called twice?");
|
NS_ASSERTION(!mChannelErrorTask, "OnChannelError called twice?");
|
||||||
|
|
||||||
|
@ -537,16 +536,16 @@ AsyncChannel::OnCloseChannel()
|
||||||
|
|
||||||
mTransport->Close();
|
mTransport->Close();
|
||||||
|
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
mChannelState = ChannelClosed;
|
mChannelState = ChannelClosed;
|
||||||
mCvar.Notify();
|
mMonitor.Notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AsyncChannel::MaybeInterceptSpecialIOMessage(const Message& msg)
|
AsyncChannel::MaybeInterceptSpecialIOMessage(const Message& msg)
|
||||||
{
|
{
|
||||||
AssertIOThread();
|
AssertIOThread();
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
if (MSG_ROUTING_NONE == msg.routing_id()
|
if (MSG_ROUTING_NONE == msg.routing_id()
|
||||||
&& GOODBYE_MESSAGE_TYPE == msg.type()) {
|
&& GOODBYE_MESSAGE_TYPE == msg.type()) {
|
||||||
|
@ -560,7 +559,7 @@ void
|
||||||
AsyncChannel::ProcessGoodbyeMessage()
|
AsyncChannel::ProcessGoodbyeMessage()
|
||||||
{
|
{
|
||||||
AssertIOThread();
|
AssertIOThread();
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
// TODO sort out Close() on this side racing with Close() on the
|
// TODO sort out Close() on this side racing with Close() on the
|
||||||
// other side
|
// other side
|
||||||
|
|
|
@ -44,8 +44,7 @@
|
||||||
#include "base/message_loop.h"
|
#include "base/message_loop.h"
|
||||||
#include "chrome/common/ipc_channel.h"
|
#include "chrome/common/ipc_channel.h"
|
||||||
|
|
||||||
#include "mozilla/CondVar.h"
|
#include "mozilla/Monitor.h"
|
||||||
#include "mozilla/Mutex.h"
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -70,8 +69,7 @@ struct HasResultCodes
|
||||||
class AsyncChannel : public IPC::Channel::Listener, protected HasResultCodes
|
class AsyncChannel : public IPC::Channel::Listener, protected HasResultCodes
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
typedef mozilla::CondVar CondVar;
|
typedef mozilla::Monitor Monitor;
|
||||||
typedef mozilla::Mutex Mutex;
|
|
||||||
|
|
||||||
enum ChannelState {
|
enum ChannelState {
|
||||||
ChannelClosed,
|
ChannelClosed,
|
||||||
|
@ -145,7 +143,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connected() const {
|
bool Connected() const {
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
return ChannelConnected == mChannelState;
|
return ChannelConnected == mChannelState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,8 +185,7 @@ protected:
|
||||||
Transport* mTransport;
|
Transport* mTransport;
|
||||||
AsyncListener* mListener;
|
AsyncListener* mListener;
|
||||||
ChannelState mChannelState;
|
ChannelState mChannelState;
|
||||||
Mutex mMutex;
|
Monitor mMonitor;
|
||||||
CondVar mCvar;
|
|
||||||
MessageLoop* mIOLoop; // thread where IO happens
|
MessageLoop* mIOLoop; // thread where IO happens
|
||||||
MessageLoop* mWorkerLoop; // thread where work is done
|
MessageLoop* mWorkerLoop; // thread where work is done
|
||||||
bool mChild; // am I the child or parent?
|
bool mChild; // am I the child or parent?
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
#include "APKOpen.h"
|
#include "APKOpen.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using mozilla::ReentrantMonitorAutoEnter;
|
using mozilla::MonitorAutoLock;
|
||||||
using mozilla::ipc::GeckoChildProcessHost;
|
using mozilla::ipc::GeckoChildProcessHost;
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
|
@ -95,7 +95,7 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
|
||||||
base::WaitableEventWatcher::Delegate* aDelegate)
|
base::WaitableEventWatcher::Delegate* aDelegate)
|
||||||
: ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum
|
: ChildProcessHost(RENDER_PROCESS), // FIXME/cjones: we should own this enum
|
||||||
mProcessType(aProcessType),
|
mProcessType(aProcessType),
|
||||||
mReentrantMonitor("mozilla.ipc.GeckChildProcessHost.mReentrantMonitor"),
|
mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"),
|
||||||
mLaunched(false),
|
mLaunched(false),
|
||||||
mChannelInitialized(false),
|
mChannelInitialized(false),
|
||||||
mDelegate(aDelegate),
|
mDelegate(aDelegate),
|
||||||
|
@ -289,14 +289,14 @@ GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts, int aTime
|
||||||
aExtraOpts, arch));
|
aExtraOpts, arch));
|
||||||
// NB: this uses a different mechanism than the chromium parent
|
// NB: this uses a different mechanism than the chromium parent
|
||||||
// class.
|
// class.
|
||||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
MonitorAutoLock lock(mMonitor);
|
||||||
PRIntervalTime waitStart = PR_IntervalNow();
|
PRIntervalTime waitStart = PR_IntervalNow();
|
||||||
PRIntervalTime current;
|
PRIntervalTime current;
|
||||||
|
|
||||||
// We'll receive several notifications, we need to exit when we
|
// We'll receive several notifications, we need to exit when we
|
||||||
// have either successfully launched or have timed out.
|
// have either successfully launched or have timed out.
|
||||||
while (!mLaunched) {
|
while (!mLaunched) {
|
||||||
mon.Wait(timeoutTicks);
|
lock.Wait(timeoutTicks);
|
||||||
|
|
||||||
if (timeoutTicks != PR_INTERVAL_NO_TIMEOUT) {
|
if (timeoutTicks != PR_INTERVAL_NO_TIMEOUT) {
|
||||||
current = PR_IntervalNow();
|
current = PR_IntervalNow();
|
||||||
|
@ -327,9 +327,9 @@ GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts)
|
||||||
|
|
||||||
// This may look like the sync launch wait, but we only delay as
|
// This may look like the sync launch wait, but we only delay as
|
||||||
// long as it takes to create the channel.
|
// long as it takes to create the channel.
|
||||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
MonitorAutoLock lock(mMonitor);
|
||||||
while (!mChannelInitialized) {
|
while (!mChannelInitialized) {
|
||||||
mon.Wait();
|
lock.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -340,9 +340,9 @@ GeckoChildProcessHost::InitializeChannel()
|
||||||
{
|
{
|
||||||
CreateChannel();
|
CreateChannel();
|
||||||
|
|
||||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
MonitorAutoLock lock(mMonitor);
|
||||||
mChannelInitialized = true;
|
mChannelInitialized = true;
|
||||||
mon.Notify();
|
lock.Notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
PRInt32 GeckoChildProcessHost::mChildCounter = 0;
|
PRInt32 GeckoChildProcessHost::mChildCounter = 0;
|
||||||
|
@ -644,13 +644,13 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
|
||||||
void
|
void
|
||||||
GeckoChildProcessHost::OnChannelConnected(int32 peer_pid)
|
GeckoChildProcessHost::OnChannelConnected(int32 peer_pid)
|
||||||
{
|
{
|
||||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
MonitorAutoLock lock(mMonitor);
|
||||||
mLaunched = true;
|
mLaunched = true;
|
||||||
|
|
||||||
if (!base::OpenPrivilegedProcessHandle(peer_pid, &mChildProcessHandle))
|
if (!base::OpenPrivilegedProcessHandle(peer_pid, &mChildProcessHandle))
|
||||||
NS_RUNTIMEABORT("can't open handle to child process");
|
NS_RUNTIMEABORT("can't open handle to child process");
|
||||||
|
|
||||||
mon.Notify();
|
lock.Notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX/cjones: these next two methods should basically never be called.
|
// XXX/cjones: these next two methods should basically never be called.
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
#include "base/waitable_event.h"
|
#include "base/waitable_event.h"
|
||||||
#include "chrome/common/child_process_host.h"
|
#include "chrome/common/child_process_host.h"
|
||||||
|
|
||||||
#include "mozilla/ReentrantMonitor.h"
|
#include "mozilla/Monitor.h"
|
||||||
|
|
||||||
#include "nsXULAppAPI.h" // for GeckoProcessType
|
#include "nsXULAppAPI.h" // for GeckoProcessType
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
@ -54,7 +54,7 @@ namespace ipc {
|
||||||
class GeckoChildProcessHost : public ChildProcessHost
|
class GeckoChildProcessHost : public ChildProcessHost
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
typedef mozilla::ReentrantMonitor ReentrantMonitor;
|
typedef mozilla::Monitor Monitor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef base::ProcessHandle ProcessHandle;
|
typedef base::ProcessHandle ProcessHandle;
|
||||||
|
@ -106,7 +106,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GeckoProcessType mProcessType;
|
GeckoProcessType mProcessType;
|
||||||
ReentrantMonitor mReentrantMonitor;
|
Monitor mMonitor;
|
||||||
bool mLaunched;
|
bool mLaunched;
|
||||||
bool mChannelInitialized;
|
bool mChannelInitialized;
|
||||||
FilePath mProcessPath;
|
FilePath mProcessPath;
|
||||||
|
|
|
@ -49,8 +49,8 @@
|
||||||
DebugAbort(__FILE__, __LINE__, #_cond,## __VA_ARGS__); \
|
DebugAbort(__FILE__, __LINE__, #_cond,## __VA_ARGS__); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
using mozilla::MutexAutoLock;
|
using mozilla::MonitorAutoLock;
|
||||||
using mozilla::MutexAutoUnlock;
|
using mozilla::MonitorAutoUnlock;
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct RunnableMethodTraits<mozilla::ipc::RPCChannel>
|
struct RunnableMethodTraits<mozilla::ipc::RPCChannel>
|
||||||
|
@ -124,7 +124,7 @@ bool
|
||||||
RPCChannel::EventOccurred() const
|
RPCChannel::EventOccurred() const
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
RPC_ASSERT(StackDepth() > 0, "not in wait loop");
|
RPC_ASSERT(StackDepth() > 0, "not in wait loop");
|
||||||
|
|
||||||
return (!Connected() ||
|
return (!Connected() ||
|
||||||
|
@ -154,7 +154,7 @@ bool
|
||||||
RPCChannel::Call(Message* msg, Message* reply)
|
RPCChannel::Call(Message* msg, Message* reply)
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertNotCurrentThreadOwns();
|
mMonitor.AssertNotCurrentThreadOwns();
|
||||||
RPC_ASSERT(!ProcessingSyncMessage(),
|
RPC_ASSERT(!ProcessingSyncMessage(),
|
||||||
"violation of sync handler invariant");
|
"violation of sync handler invariant");
|
||||||
RPC_ASSERT(msg->is_rpc(), "can only Call() RPC messages here");
|
RPC_ASSERT(msg->is_rpc(), "can only Call() RPC messages here");
|
||||||
|
@ -166,7 +166,7 @@ RPCChannel::Call(Message* msg, Message* reply)
|
||||||
Message copy = *msg;
|
Message copy = *msg;
|
||||||
CxxStackFrame f(*this, OUT_MESSAGE, ©);
|
CxxStackFrame f(*this, OUT_MESSAGE, ©);
|
||||||
|
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (!Connected()) {
|
if (!Connected()) {
|
||||||
ReportConnectionError("RPCChannel");
|
ReportConnectionError("RPCChannel");
|
||||||
|
@ -238,7 +238,7 @@ RPCChannel::Call(Message* msg, Message* reply)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recvd.is_sync() && !recvd.is_rpc()) {
|
if (!recvd.is_sync() && !recvd.is_rpc()) {
|
||||||
MutexAutoUnlock unlock(mMutex);
|
MonitorAutoUnlock unlock(mMonitor);
|
||||||
|
|
||||||
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
|
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
|
||||||
AsyncChannel::OnDispatchMessage(recvd);
|
AsyncChannel::OnDispatchMessage(recvd);
|
||||||
|
@ -249,7 +249,7 @@ RPCChannel::Call(Message* msg, Message* reply)
|
||||||
if (recvd.is_sync()) {
|
if (recvd.is_sync()) {
|
||||||
RPC_ASSERT(mPending.empty(),
|
RPC_ASSERT(mPending.empty(),
|
||||||
"other side should have been blocked");
|
"other side should have been blocked");
|
||||||
MutexAutoUnlock unlock(mMutex);
|
MonitorAutoUnlock unlock(mMonitor);
|
||||||
|
|
||||||
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
|
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
|
||||||
SyncChannel::OnDispatchMessage(recvd);
|
SyncChannel::OnDispatchMessage(recvd);
|
||||||
|
@ -301,10 +301,10 @@ RPCChannel::Call(Message* msg, Message* reply)
|
||||||
|
|
||||||
// in-call. process in a new stack frame.
|
// in-call. process in a new stack frame.
|
||||||
|
|
||||||
// "snapshot" the current stack depth while we own the Mutex
|
// "snapshot" the current stack depth while we own the Monitor
|
||||||
size_t stackDepth = StackDepth();
|
size_t stackDepth = StackDepth();
|
||||||
{
|
{
|
||||||
MutexAutoUnlock unlock(mMutex);
|
MonitorAutoUnlock unlock(mMonitor);
|
||||||
// someone called in to us from the other side. handle the call
|
// someone called in to us from the other side. handle the call
|
||||||
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
|
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
|
||||||
Incall(recvd, stackDepth);
|
Incall(recvd, stackDepth);
|
||||||
|
@ -319,7 +319,7 @@ void
|
||||||
RPCChannel::MaybeUndeferIncall()
|
RPCChannel::MaybeUndeferIncall()
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
if (mDeferred.empty())
|
if (mDeferred.empty())
|
||||||
return;
|
return;
|
||||||
|
@ -348,7 +348,7 @@ void
|
||||||
RPCChannel::EnqueuePendingMessages()
|
RPCChannel::EnqueuePendingMessages()
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
MaybeUndeferIncall();
|
MaybeUndeferIncall();
|
||||||
|
|
||||||
|
@ -370,10 +370,10 @@ void
|
||||||
RPCChannel::FlushPendingRPCQueue()
|
RPCChannel::FlushPendingRPCQueue()
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertNotCurrentThreadOwns();
|
mMonitor.AssertNotCurrentThreadOwns();
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (mDeferred.empty()) {
|
if (mDeferred.empty()) {
|
||||||
if (mPending.empty())
|
if (mPending.empty())
|
||||||
|
@ -395,11 +395,11 @@ RPCChannel::OnMaybeDequeueOne()
|
||||||
// messages here
|
// messages here
|
||||||
|
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertNotCurrentThreadOwns();
|
mMonitor.AssertNotCurrentThreadOwns();
|
||||||
|
|
||||||
Message recvd;
|
Message recvd;
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (!Connected()) {
|
if (!Connected()) {
|
||||||
ReportConnectionError("RPCChannel");
|
ReportConnectionError("RPCChannel");
|
||||||
|
@ -439,7 +439,7 @@ void
|
||||||
RPCChannel::Incall(const Message& call, size_t stackDepth)
|
RPCChannel::Incall(const Message& call, size_t stackDepth)
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertNotCurrentThreadOwns();
|
mMonitor.AssertNotCurrentThreadOwns();
|
||||||
RPC_ASSERT(call.is_rpc() && !call.is_reply(), "wrong message type");
|
RPC_ASSERT(call.is_rpc() && !call.is_reply(), "wrong message type");
|
||||||
|
|
||||||
// Race detection: see the long comment near
|
// Race detection: see the long comment near
|
||||||
|
@ -502,7 +502,7 @@ void
|
||||||
RPCChannel::DispatchIncall(const Message& call)
|
RPCChannel::DispatchIncall(const Message& call)
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertNotCurrentThreadOwns();
|
mMonitor.AssertNotCurrentThreadOwns();
|
||||||
RPC_ASSERT(call.is_rpc() && !call.is_reply(),
|
RPC_ASSERT(call.is_rpc() && !call.is_reply(),
|
||||||
"wrong message type");
|
"wrong message type");
|
||||||
|
|
||||||
|
@ -523,7 +523,7 @@ RPCChannel::DispatchIncall(const Message& call)
|
||||||
reply->set_seqno(call.seqno());
|
reply->set_seqno(call.seqno());
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
if (ChannelConnected == mChannelState)
|
if (ChannelConnected == mChannelState)
|
||||||
SendThroughTransport(reply);
|
SendThroughTransport(reply);
|
||||||
}
|
}
|
||||||
|
@ -578,7 +578,7 @@ RPCChannel::BlockOnParent()
|
||||||
if (!mChild)
|
if (!mChild)
|
||||||
NS_RUNTIMEABORT("child tried to block parent");
|
NS_RUNTIMEABORT("child tried to block parent");
|
||||||
|
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (mBlockedOnParent || AwaitingSyncReply() || 0 < StackDepth())
|
if (mBlockedOnParent || AwaitingSyncReply() || 0 < StackDepth())
|
||||||
NS_RUNTIMEABORT("attempt to block child when it's already blocked");
|
NS_RUNTIMEABORT("attempt to block child when it's already blocked");
|
||||||
|
@ -602,7 +602,7 @@ RPCChannel::BlockOnParent()
|
||||||
Message recvd = mPending.front();
|
Message recvd = mPending.front();
|
||||||
mPending.pop();
|
mPending.pop();
|
||||||
|
|
||||||
MutexAutoUnlock unlock(mMutex);
|
MonitorAutoUnlock unlock(mMonitor);
|
||||||
|
|
||||||
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
|
CxxStackFrame f(*this, IN_MESSAGE, &recvd);
|
||||||
if (recvd.is_rpc()) {
|
if (recvd.is_rpc()) {
|
||||||
|
@ -628,7 +628,7 @@ RPCChannel::UnblockFromParent()
|
||||||
|
|
||||||
if (!mChild)
|
if (!mChild)
|
||||||
NS_RUNTIMEABORT("child tried to block parent");
|
NS_RUNTIMEABORT("child tried to block parent");
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
mBlockedOnParent = false;
|
mBlockedOnParent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,7 +637,7 @@ RPCChannel::ExitedCxxStack()
|
||||||
{
|
{
|
||||||
Listener()->OnExitedCxxStack();
|
Listener()->OnExitedCxxStack();
|
||||||
if (mSawRPCOutMsg) {
|
if (mSawRPCOutMsg) {
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
// see long comment in OnMaybeDequeueOne()
|
// see long comment in OnMaybeDequeueOne()
|
||||||
EnqueuePendingMessages();
|
EnqueuePendingMessages();
|
||||||
mSawRPCOutMsg = false;
|
mSawRPCOutMsg = false;
|
||||||
|
@ -710,7 +710,7 @@ void
|
||||||
RPCChannel::OnMessageReceived(const Message& msg)
|
RPCChannel::OnMessageReceived(const Message& msg)
|
||||||
{
|
{
|
||||||
AssertIOThread();
|
AssertIOThread();
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (MaybeInterceptSpecialIOMessage(msg))
|
if (MaybeInterceptSpecialIOMessage(msg))
|
||||||
return;
|
return;
|
||||||
|
@ -740,7 +740,7 @@ RPCChannel::OnChannelError()
|
||||||
{
|
{
|
||||||
AssertIOThread();
|
AssertIOThread();
|
||||||
|
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (ChannelClosing != mChannelState)
|
if (ChannelClosing != mChannelState)
|
||||||
mChannelState = ChannelError;
|
mChannelState = ChannelError;
|
||||||
|
|
|
@ -311,7 +311,7 @@ protected:
|
||||||
|
|
||||||
// Called from both threads
|
// Called from both threads
|
||||||
size_t StackDepth() const {
|
size_t StackDepth() const {
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
return mStack.size();
|
return mStack.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,7 +425,7 @@ protected:
|
||||||
// !mCxxStackFrames.empty() => RPCChannel code on C++ stack
|
// !mCxxStackFrames.empty() => RPCChannel code on C++ stack
|
||||||
//
|
//
|
||||||
// This member is only accessed on the worker thread, and so is
|
// This member is only accessed on the worker thread, and so is
|
||||||
// not protected by mMutex. It is managed exclusively by the
|
// not protected by mMonitor. It is managed exclusively by the
|
||||||
// helper |class CxxStackFrame|.
|
// helper |class CxxStackFrame|.
|
||||||
std::vector<RPCFrame> mCxxStackFrames;
|
std::vector<RPCFrame> mCxxStackFrames;
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
#include "nsDebug.h"
|
#include "nsDebug.h"
|
||||||
#include "nsTraceRefcnt.h"
|
#include "nsTraceRefcnt.h"
|
||||||
|
|
||||||
using mozilla::MutexAutoLock;
|
using mozilla::MonitorAutoLock;
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct RunnableMethodTraits<mozilla::ipc::SyncChannel>
|
struct RunnableMethodTraits<mozilla::ipc::SyncChannel>
|
||||||
|
@ -88,7 +88,7 @@ bool
|
||||||
SyncChannel::EventOccurred()
|
SyncChannel::EventOccurred()
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
NS_ABORT_IF_FALSE(AwaitingSyncReply(), "not in wait loop");
|
NS_ABORT_IF_FALSE(AwaitingSyncReply(), "not in wait loop");
|
||||||
|
|
||||||
return (!Connected() || 0 != mRecvd.type());
|
return (!Connected() || 0 != mRecvd.type());
|
||||||
|
@ -98,7 +98,7 @@ bool
|
||||||
SyncChannel::Send(Message* msg, Message* reply)
|
SyncChannel::Send(Message* msg, Message* reply)
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertNotCurrentThreadOwns();
|
mMonitor.AssertNotCurrentThreadOwns();
|
||||||
NS_ABORT_IF_FALSE(!ProcessingSyncMessage(),
|
NS_ABORT_IF_FALSE(!ProcessingSyncMessage(),
|
||||||
"violation of sync handler invariant");
|
"violation of sync handler invariant");
|
||||||
NS_ABORT_IF_FALSE(msg->is_sync(), "can only Send() sync messages here");
|
NS_ABORT_IF_FALSE(msg->is_sync(), "can only Send() sync messages here");
|
||||||
|
@ -109,7 +109,7 @@ SyncChannel::Send(Message* msg, Message* reply)
|
||||||
|
|
||||||
msg->set_seqno(NextSeqno());
|
msg->set_seqno(NextSeqno());
|
||||||
|
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (!Connected()) {
|
if (!Connected()) {
|
||||||
ReportConnectionError("SyncChannel");
|
ReportConnectionError("SyncChannel");
|
||||||
|
@ -181,7 +181,7 @@ SyncChannel::OnDispatchMessage(const Message& msg)
|
||||||
reply->set_seqno(msg.seqno());
|
reply->set_seqno(msg.seqno());
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
if (ChannelConnected == mChannelState)
|
if (ChannelConnected == mChannelState)
|
||||||
SendThroughTransport(reply);
|
SendThroughTransport(reply);
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ SyncChannel::OnMessageReceived(const Message& msg)
|
||||||
return AsyncChannel::OnMessageReceived(msg);
|
return AsyncChannel::OnMessageReceived(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (MaybeInterceptSpecialIOMessage(msg))
|
if (MaybeInterceptSpecialIOMessage(msg))
|
||||||
return;
|
return;
|
||||||
|
@ -223,7 +223,7 @@ SyncChannel::OnChannelError()
|
||||||
{
|
{
|
||||||
AssertIOThread();
|
AssertIOThread();
|
||||||
|
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
if (ChannelClosing != mChannelState)
|
if (ChannelClosing != mChannelState)
|
||||||
mChannelState = ChannelError;
|
mChannelState = ChannelError;
|
||||||
|
@ -253,11 +253,11 @@ bool
|
||||||
SyncChannel::ShouldContinueFromTimeout()
|
SyncChannel::ShouldContinueFromTimeout()
|
||||||
{
|
{
|
||||||
AssertWorkerThread();
|
AssertWorkerThread();
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
bool cont;
|
bool cont;
|
||||||
{
|
{
|
||||||
MutexAutoUnlock unlock(mMutex);
|
MonitorAutoUnlock unlock(mMonitor);
|
||||||
cont = static_cast<SyncListener*>(mListener)->OnReplyTimeout();
|
cont = static_cast<SyncListener*>(mListener)->OnReplyTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ SyncChannel::WaitForNotify()
|
||||||
// XXX could optimize away this syscall for "no timeout" case if desired
|
// XXX could optimize away this syscall for "no timeout" case if desired
|
||||||
PRIntervalTime waitStart = PR_IntervalNow();
|
PRIntervalTime waitStart = PR_IntervalNow();
|
||||||
|
|
||||||
mCvar.Wait(timeout);
|
mMonitor.Wait(timeout);
|
||||||
|
|
||||||
// if the timeout didn't expire, we know we received an event.
|
// if the timeout didn't expire, we know we received an event.
|
||||||
// The converse is not true.
|
// The converse is not true.
|
||||||
|
@ -305,7 +305,7 @@ SyncChannel::WaitForNotify()
|
||||||
void
|
void
|
||||||
SyncChannel::NotifyWorkerThread()
|
SyncChannel::NotifyWorkerThread()
|
||||||
{
|
{
|
||||||
mCvar.Notify();
|
mMonitor.Notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // ifndef OS_WIN
|
#endif // ifndef OS_WIN
|
||||||
|
|
|
@ -171,7 +171,7 @@ protected:
|
||||||
|
|
||||||
// On both
|
// On both
|
||||||
bool AwaitingSyncReply() const {
|
bool AwaitingSyncReply() const {
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
return mPendingReply != 0;
|
return mPendingReply != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -655,7 +655,7 @@ RPCChannel::SpinInternalEventLoop()
|
||||||
|
|
||||||
// Don't get wrapped up in here if the child connection dies.
|
// Don't get wrapped up in here if the child connection dies.
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
if (!Connected()) {
|
if (!Connected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -692,7 +692,7 @@ RPCChannel::SpinInternalEventLoop()
|
||||||
bool
|
bool
|
||||||
SyncChannel::WaitForNotify()
|
SyncChannel::WaitForNotify()
|
||||||
{
|
{
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
// Initialize global objects used in deferred messaging.
|
// Initialize global objects used in deferred messaging.
|
||||||
Init();
|
Init();
|
||||||
|
@ -700,7 +700,7 @@ SyncChannel::WaitForNotify()
|
||||||
NS_ASSERTION(mTopFrame && !mTopFrame->mRPC,
|
NS_ASSERTION(mTopFrame && !mTopFrame->mRPC,
|
||||||
"Top frame is not a sync frame!");
|
"Top frame is not a sync frame!");
|
||||||
|
|
||||||
MutexAutoUnlock unlock(mMutex);
|
MonitorAutoUnlock unlock(mMonitor);
|
||||||
|
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
|
|
||||||
|
@ -730,7 +730,7 @@ SyncChannel::WaitForNotify()
|
||||||
MSG msg = { 0 };
|
MSG msg = { 0 };
|
||||||
// Don't get wrapped up in here if the child connection dies.
|
// Don't get wrapped up in here if the child connection dies.
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
if (!Connected()) {
|
if (!Connected()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -814,7 +814,7 @@ SyncChannel::WaitForNotify()
|
||||||
bool
|
bool
|
||||||
RPCChannel::WaitForNotify()
|
RPCChannel::WaitForNotify()
|
||||||
{
|
{
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
|
|
||||||
if (!StackDepth() && !mBlockedOnParent) {
|
if (!StackDepth() && !mBlockedOnParent) {
|
||||||
// There is currently no way to recover from this condition.
|
// There is currently no way to recover from this condition.
|
||||||
|
@ -827,7 +827,7 @@ RPCChannel::WaitForNotify()
|
||||||
NS_ASSERTION(mTopFrame && mTopFrame->mRPC,
|
NS_ASSERTION(mTopFrame && mTopFrame->mRPC,
|
||||||
"Top frame is not a sync frame!");
|
"Top frame is not a sync frame!");
|
||||||
|
|
||||||
MutexAutoUnlock unlock(mMutex);
|
MonitorAutoUnlock unlock(mMonitor);
|
||||||
|
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
|
|
||||||
|
@ -890,7 +890,7 @@ RPCChannel::WaitForNotify()
|
||||||
|
|
||||||
// Don't get wrapped up in here if the child connection dies.
|
// Don't get wrapped up in here if the child connection dies.
|
||||||
{
|
{
|
||||||
MutexAutoLock lock(mMutex);
|
MonitorAutoLock lock(mMonitor);
|
||||||
if (!Connected()) {
|
if (!Connected()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -954,7 +954,7 @@ RPCChannel::WaitForNotify()
|
||||||
void
|
void
|
||||||
SyncChannel::NotifyWorkerThread()
|
SyncChannel::NotifyWorkerThread()
|
||||||
{
|
{
|
||||||
mMutex.AssertCurrentThreadOwns();
|
mMonitor.AssertCurrentThreadOwns();
|
||||||
NS_ASSERTION(mEvent, "No signal event to set, this is really bad!");
|
NS_ASSERTION(mEvent, "No signal event to set, this is really bad!");
|
||||||
if (!SetEvent(mEvent)) {
|
if (!SetEvent(mEvent)) {
|
||||||
NS_WARNING("Failed to set NotifyWorkerThread event!");
|
NS_WARNING("Failed to set NotifyWorkerThread event!");
|
||||||
|
|
Загрузка…
Ссылка в новой задаче