Recover from C++ exceptions in AsioExternalThreadEvent::unserialize(), part1

AsioExternalThreadEvent::unserialize() may legally throw PHP exceptions.
When that happens, construction of PHP exceptions reenters VM, surprised
flag is checked and pending C++ exceptions may be thrown.

Let's make sure the event is properly destroyed. If it is not, the web
request will get stuck forever waiting for the finished event to finish.
Esse commit está contido em:
Jan Oravec
2013-06-15 18:23:02 -07:00
commit de Sara Golemon
commit d6e869dfa9
2 arquivos alterados com 27 adições e 15 exclusões
@@ -80,6 +80,19 @@ void c_ExternalThreadEventWaitHandle::initialize(AsioExternalThreadEvent* event,
}
}
void c_ExternalThreadEventWaitHandle::destroyEvent() {
// destroy event and its private data
m_event->release();
m_event = nullptr;
m_privData = nullptr;
// unregister from sweep()
unregister();
// drop ownership by pending event (see initialize())
decRefObj(this);
}
void c_ExternalThreadEventWaitHandle::abandon(bool sweeping) {
assert(getState() == STATE_WAITING);
assert(getCount() == 1 || sweeping);
@@ -88,11 +101,8 @@ void c_ExternalThreadEventWaitHandle::abandon(bool sweeping) {
getContext()->unregisterExternalThreadEvent(m_index);
}
// event is abandoned, destroy it, unregister sweepable and decref ownership
m_event->release();
m_event = nullptr;
unregister();
decRefObj(this);
// clean up
destroyEvent();
}
void c_ExternalThreadEventWaitHandle::process() {
@@ -102,22 +112,23 @@ void c_ExternalThreadEventWaitHandle::process() {
getContext()->unregisterExternalThreadEvent(m_index);
}
// clean up once event is processed
auto exit_guard = folly::makeGuard([&] { destroyEvent(); });
TypedValue result;
try {
TypedValue result;
m_event->unserialize(&result);
assert(tvIsPlausible(&result));
setResult(&result);
tvRefcountedDecRefCell(&result);
} catch (const Object& exception) {
setException(exception.get());
return;
} catch (...) {
setException(AsioSession::Get()->getAbruptInterruptException().get());
throw;
}
// event is processed, destroy it, unregister sweepable and decref ownership
m_event->release();
m_event = nullptr;
m_privData = nullptr;
unregister();
decRefObj(this);
assert(tvIsPlausible(&result));
setResult(&result);
tvRefcountedDecRefCell(&result);
}
String c_ExternalThreadEventWaitHandle::getName() {
+1
Ver Arquivo
@@ -493,6 +493,7 @@ class c_ExternalThreadEventWaitHandle : public c_WaitableWaitHandle, public Swee
private:
void initialize(AsioExternalThreadEvent* event, ObjectData* priv_data);
void destroyEvent();
c_ExternalThreadEventWaitHandle* m_nextToProcess;
AsioExternalThreadEvent* m_event;