Bug 540004, part 3: Add a ShouldContinue() interface to IPDL actors that allows them to decide how a hang should be treated. r=bent

--HG--
extra : transplant_source : m%5E%40%9FYJ%EFI%9F%E5%25s%8E%1A%AF%BEQ%01va
This commit is contained in:
Chris Jones 2010-02-09 18:02:55 -06:00
parent 3ea312dfdf
commit feb0d735b0
5 changed files with 53 additions and 1 deletions

View File

@ -61,6 +61,7 @@ public:
virtual void OnChannelClose() = 0;
virtual void OnChannelError() = 0;
virtual Result OnMessageReceived(const Message& aMessage) = 0;
virtual bool OnReplyTimeout() = 0;
virtual Result OnMessageReceived(const Message& aMessage,
Message*& aReply) = 0;
virtual Result OnCallReceived(const Message& aMessage,

View File

@ -237,7 +237,11 @@ SyncChannel::ShouldContinueFromTimeout()
AssertWorkerThread();
mMutex.AssertCurrentThreadOwns();
bool cont = true;
bool cont;
{
MutexAutoUnlock unlock(mMutex);
cont = static_cast<SyncListener*>(mListener)->OnReplyTimeout();
}
if (!cont) {
// NB: there's a sublety here. If parents were allowed to

View File

@ -67,6 +67,7 @@ public:
virtual void OnChannelClose() = 0;
virtual void OnChannelError() = 0;
virtual Result OnMessageReceived(const Message& aMessage) = 0;
virtual bool OnReplyTimeout() = 0;
virtual Result OnMessageReceived(const Message& aMessage,
Message*& aReply) = 0;
};
@ -81,6 +82,11 @@ public:
// Synchronously send |msg| (i.e., wait for |reply|)
bool Send(Message* msg, Message* reply);
void SetReplyTimeoutMs(int32 aTimeoutMs) {
AssertWorkerThread();
mTimeoutMs = (aTimeoutMs <= 0) ? kNoTimeout : aTimeoutMs;
}
// Override the AsyncChannel handler so we can dispatch sync messages
NS_OVERRIDE virtual void OnMessageReceived(const Message& msg);
NS_OVERRIDE virtual void OnChannelError();

View File

@ -342,6 +342,7 @@ Any type, naked or pointer, can be const (const T) or ref (T&).
T=copy.deepcopy(self.T, memo))
Type.BOOL = Type('bool')
Type.INT = Type('int')
Type.INT32 = Type('int32')
Type.INTPTR = Type('intptr_t')
Type.UINT32 = Type('uint32')
Type.SIZE = Type('size_t')

View File

@ -1344,6 +1344,10 @@ class Protocol(ipdl.ast.Protocol):
def otherProcessMethod(self):
return ExprVar('OtherProcess')
def shouldContinueFromTimeoutVar(self):
assert self.decl.type.isToplevel()
return ExprVar('ShouldContinueFromReplyTimeout')
def nextActorIdExpr(self, side):
assert self.decl.type.isToplevel()
if side is 'parent': op = '++'
@ -2629,6 +2633,14 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
Whitespace.NL
])
if ptype.isToplevel():
# bool ShouldContinueFromReplyTimeout(); default to |true|
shouldcontinue = MethodDefn(
MethodDecl(p.shouldContinueFromTimeoutVar().name,
ret=Type.BOOL, virtual=1))
shouldcontinue.addstmt(StmtReturn(ExprLiteral.TRUE))
self.cls.addstmts([ shouldcontinue, Whitespace.NL ])
self.cls.addstmts((
[ Label.PRIVATE ]
+ self.standardTypedefs()
@ -2698,6 +2710,18 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
ExprCall(ExprSelect(p.channelVar(), '.', 'Close'))))
self.cls.addstmts([ closemeth, Whitespace.NL ])
if ptype.talksSync() or ptype.talksRpc():
# SetReplyTimeoutMs()
timeoutvar = ExprVar('aTimeoutMs')
settimeout = MethodDefn(MethodDecl(
'SetReplyTimeoutMs',
params=[ Decl(Type.INT32, timeoutvar.name) ]))
settimeout.addstmt(StmtExpr(
ExprCall(
ExprSelect(p.channelVar(), '.', 'SetReplyTimeoutMs'),
args=[ timeoutvar ])))
self.cls.addstmts([ settimeout, Whitespace.NL ])
if not ptype.isToplevel():
if 1 == len(p.managers):
## manager()
@ -2820,6 +2844,22 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
destroysubtreevar = ExprVar('DestroySubtree')
deallocsubtreevar = ExprVar('DeallocSubtree')
# OnReplyTimeout()
if toplevel.talksSync() or toplevel.talksRpc():
ontimeout = MethodDefn(
MethodDecl('OnReplyTimeout', ret=Type.BOOL))
if ptype.isToplevel():
ontimeout.addstmt(StmtReturn(
ExprCall(p.shouldContinueFromTimeoutVar())))
else:
ontimeout.addstmts([
_runtimeAbort("`OnReplyTimeout' called on non-toplevel actor"),
StmtReturn(ExprLiteral.FALSE)
])
self.cls.addstmts([ ontimeout, Whitespace.NL ])
# OnChannelClose()
onclose = MethodDefn(MethodDecl('OnChannelClose'))
if ptype.isToplevel():