size_t check_request_surprise() { auto& info = TI(); auto& p = info.m_reqInjectionData; auto const flags = fetchAndClearSurpriseFlags(); auto const do_timedout = (flags & TimedOutFlag) && !p.getDebuggerAttached(); auto const do_memExceeded = flags & MemExceededFlag; auto const do_signaled = flags & SignaledFlag; auto const do_cpuTimedOut = (flags & CPUTimedOutFlag) && !p.getDebuggerAttached(); auto const do_GC = flags & PendingGCFlag; // Start with any pending exception that might be on the thread. auto pendingException = info.m_pendingException; info.m_pendingException = nullptr; if (do_timedout) { p.setCPUTimeout(0); // Stop CPU timer so we won't time out twice. if (pendingException) { setSurpriseFlag(TimedOutFlag); } else { pendingException = generate_request_timeout_exception(); } } // Don't bother with the CPU timeout if we're already handling a wall timeout. if (do_cpuTimedOut && !do_timedout) { p.setTimeout(0); // Stop wall timer so we won't time out twice. if (pendingException) { setSurpriseFlag(CPUTimedOutFlag); } else { pendingException = generate_request_cpu_timeout_exception(); } } if (do_memExceeded) { if (pendingException) { setSurpriseFlag(MemExceededFlag); } else { pendingException = generate_memory_exceeded_exception(); } } if (do_GC) { if (StickyFlags & PendingGCFlag) { clearSurpriseFlag(PendingGCFlag); } if (RuntimeOption::EvalEnableGC) { MM().collect("surprise"); } else { MM().checkHeap("surprise"); } } if (do_signaled) { HHVM_FN(pcntl_signal_dispatch)(); } if (pendingException) { pendingException->throwException(); } return flags; }
ssize_t check_request_surprise(ThreadInfo* info) { auto& p = info->m_reqInjectionData; auto const flags = p.fetchAndClearFlags(); bool do_timedout = (flags & RequestInjectionData::TimedOutFlag) && !p.getDebuggerAttached(); bool do_cpuTimedOut = (flags & RequestInjectionData::CPUTimedOutFlag) && !p.getDebuggerAttached(); bool do_memExceeded = (flags & RequestInjectionData::MemExceededFlag); bool do_signaled = (flags & RequestInjectionData::SignaledFlag); bool do_intervalTimer = (flags & RequestInjectionData::IntervalTimerFlag); // Start with any pending exception that might be on the thread. auto pendingException = info->m_pendingException; info->m_pendingException = nullptr; if (do_timedout) { p.setCPUTimeout(0); // Stop CPU timer so we won't time out twice. if (pendingException) { p.setTimedOutFlag(); } else { pendingException = generate_request_timeout_exception(); } } // Don't bother with the CPU timeout if we're already handling a wall timeout. if (do_cpuTimedOut && !do_timedout) { p.setTimeout(0); // Stop wall timer so we won't time out twice. if (pendingException) { p.setCPUTimedOutFlag(); } else { pendingException = generate_request_cpu_timeout_exception(); } } if (do_memExceeded) { if (pendingException) { p.setMemExceededFlag(); } else { pendingException = generate_memory_exceeded_exception(); } } if (do_signaled) { extern bool HHVM_FN(pcntl_signal_dispatch)(); HHVM_FN(pcntl_signal_dispatch)(); } if (do_intervalTimer) { IntervalTimer::RunCallbacks(); } if (pendingException) { pendingException->throwException(); } return flags; }
ssize_t check_request_surprise(ThreadInfo* info) { auto& p = info->m_reqInjectionData; bool do_timedout, do_memExceeded, do_signaled; ssize_t flags = p.fetchAndClearFlags(); do_timedout = (flags & RequestInjectionData::TimedOutFlag) && !p.getDebuggerAttached(); do_memExceeded = (flags & RequestInjectionData::MemExceededFlag); do_signaled = (flags & RequestInjectionData::SignaledFlag); // Start with any pending exception that might be on the thread. Exception* pendingException = info->m_pendingException; info->m_pendingException = nullptr; if (do_timedout) { if (pendingException) { p.setTimedOutFlag(); } else { pendingException = generate_request_timeout_exception(); } } if (do_memExceeded) { if (pendingException) { p.setMemExceededFlag(); } else { pendingException = generate_memory_exceeded_exception(); } } if (do_signaled) { extern bool f_pcntl_signal_dispatch(); f_pcntl_signal_dispatch(); } if (pendingException) { pendingException->throwException(); } return flags; }
size_t check_request_surprise() { auto& info = TI(); auto& p = info.m_reqInjectionData; auto const flags = fetchAndClearSurpriseFlags(); auto const do_timedout = (flags & TimedOutFlag) && !p.getDebuggerAttached(); auto const do_memExceeded = flags & MemExceededFlag; auto const do_memThreshold = flags & MemThresholdFlag; auto const do_signaled = flags & SignaledFlag; auto const do_cpuTimedOut = (flags & CPUTimedOutFlag) && !p.getDebuggerAttached(); auto const do_GC = flags & PendingGCFlag; // Start with any pending exception that might be on the thread. auto pendingException = info.m_pendingException; info.m_pendingException = nullptr; if (do_timedout) { p.setCPUTimeout(0); // Stop CPU timer so we won't time out twice. if (pendingException) { setSurpriseFlag(TimedOutFlag); } else { pendingException = generate_request_timeout_exception(); } } // Don't bother with the CPU timeout if we're already handling a wall timeout. if (do_cpuTimedOut && !do_timedout) { p.setTimeout(0); // Stop wall timer so we won't time out twice. if (pendingException) { setSurpriseFlag(CPUTimedOutFlag); } else { pendingException = generate_request_cpu_timeout_exception(); } } if (do_memExceeded) { if (pendingException) { setSurpriseFlag(MemExceededFlag); } else { pendingException = generate_memory_exceeded_exception(); } } if (do_memThreshold) { clearSurpriseFlag(MemThresholdFlag); if (!g_context->m_memThresholdCallback.isNull()) { VMRegAnchor _; try { vm_call_user_func(g_context->m_memThresholdCallback, empty_array()); } catch (Object& ex) { raise_error("Uncaught exception escaping mem Threshold callback: %s", ex.toString().data()); } } } if (do_GC) { VMRegAnchor _; if (RuntimeOption::EvalEnableGC) { MM().collect("surprise"); } else { MM().checkHeap("surprise"); } } if (do_signaled) { HHVM_FN(pcntl_signal_dispatch)(); } if (pendingException) { pendingException->throwException(); } return flags; }
size_t handle_request_surprise(c_WaitableWaitHandle* wh, size_t mask) { auto& info = TI(); auto& p = info.m_reqInjectionData; auto const flags = fetchAndClearSurpriseFlags() & mask; auto const debugging = p.getDebuggerAttached(); // Start with any pending exception that might be on the thread. auto pendingException = info.m_pendingException; info.m_pendingException = nullptr; if ((flags & TimedOutFlag) && !debugging) { p.setCPUTimeout(0); // Stop CPU timer so we won't time out twice. if (pendingException) { setSurpriseFlag(TimedOutFlag); } else { pendingException = generate_request_timeout_exception(wh); } } else if ((flags & CPUTimedOutFlag) && !debugging) { // Don't bother with the CPU timeout if we're already handling a wall // timeout. p.setTimeout(0); // Stop wall timer so we won't time out twice. if (pendingException) { setSurpriseFlag(CPUTimedOutFlag); } else { pendingException = generate_request_cpu_timeout_exception(wh); } } if (flags & MemExceededFlag) { if (pendingException) { setSurpriseFlag(MemExceededFlag); } else { pendingException = generate_memory_exceeded_exception(wh); } } if (flags & PendingGCFlag) { if (StickyFlags & PendingGCFlag) { clearSurpriseFlag(PendingGCFlag); } if (RuntimeOption::EvalEnableGC) { MM().collect("surprise"); } else { MM().checkHeap("surprise"); } } if (flags & SignaledFlag) { HHVM_FN(pcntl_signal_dispatch)(); } if (flags & PendingPerfEventFlag) { if (StickyFlags & PendingPerfEventFlag) { clearSurpriseFlag(PendingPerfEventFlag); } perf_event_consume(record_perf_mem_event); } if (pendingException) { pendingException->throwException(); } return flags; }