framescheduler: fix edge case crashes
rare UAFs because renderMonitor can call onDisconnect (ugh, that should be changed...) fixes #11073
This commit is contained in:
parent
1cbb62ed6a
commit
78c9e2080c
3 changed files with 38 additions and 12 deletions
|
|
@ -63,7 +63,10 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
|
|
||||||
g_pEventLoopManager->doLater([] { g_pConfigManager->ensurePersistentWorkspacesPresent(); });
|
g_pEventLoopManager->doLater([] { g_pConfigManager->ensurePersistentWorkspacesPresent(); });
|
||||||
|
|
||||||
m_listeners.frame = m_output->events.frame.listen([this] { m_frameScheduler->onFrame(); });
|
m_listeners.frame = m_output->events.frame.listen([this] {
|
||||||
|
if (m_frameScheduler)
|
||||||
|
m_frameScheduler->onFrame();
|
||||||
|
});
|
||||||
m_listeners.commit = m_output->events.commit.listen([this] {
|
m_listeners.commit = m_output->events.commit.listen([this] {
|
||||||
if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER
|
if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER
|
||||||
PROTO::screencopy->onOutputCommit(m_self.lock());
|
PROTO::screencopy->onOutputCommit(m_self.lock());
|
||||||
|
|
@ -127,7 +130,8 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
applyMonitorRule(&rule);
|
applyMonitorRule(&rule);
|
||||||
});
|
});
|
||||||
|
|
||||||
m_frameScheduler = makeUnique<CMonitorFrameScheduler>(m_self.lock());
|
m_frameScheduler = makeUnique<CMonitorFrameScheduler>(m_self.lock());
|
||||||
|
m_frameScheduler->m_self = WP<CMonitorFrameScheduler>(m_frameScheduler);
|
||||||
|
|
||||||
m_tearingState.canTear = m_output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM;
|
m_tearingState.canTear = m_output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,16 @@ void CMonitorFrameScheduler::onSyncFired() {
|
||||||
m_renderAtFrame = false; // block frame rendering, we already scheduled
|
m_renderAtFrame = false; // block frame rendering, we already scheduled
|
||||||
|
|
||||||
m_lastRenderBegun = hrc::now();
|
m_lastRenderBegun = hrc::now();
|
||||||
|
|
||||||
|
// get a ref to ourselves. renderMonitor can destroy this scheduler if it decides to perform a monitor reload
|
||||||
|
// FIXME: this is horrible. "renderMonitor" should not be able to do that.
|
||||||
|
auto self = m_self;
|
||||||
|
|
||||||
g_pHyprRenderer->renderMonitor(m_monitor.lock(), false);
|
g_pHyprRenderer->renderMonitor(m_monitor.lock(), false);
|
||||||
|
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
|
||||||
onFinishRender();
|
onFinishRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,14 +108,23 @@ void CMonitorFrameScheduler::onFrame() {
|
||||||
Debug::log(TRACE, "CMonitorFrameScheduler: {} -> frame event, render = true, rendering normally.", m_monitor->m_name);
|
Debug::log(TRACE, "CMonitorFrameScheduler: {} -> frame event, render = true, rendering normally.", m_monitor->m_name);
|
||||||
|
|
||||||
m_lastRenderBegun = hrc::now();
|
m_lastRenderBegun = hrc::now();
|
||||||
|
|
||||||
|
// get a ref to ourselves. renderMonitor can destroy this scheduler if it decides to perform a monitor reload
|
||||||
|
// FIXME: this is horrible. "renderMonitor" should not be able to do that.
|
||||||
|
auto self = m_self;
|
||||||
|
|
||||||
g_pHyprRenderer->renderMonitor(m_monitor.lock());
|
g_pHyprRenderer->renderMonitor(m_monitor.lock());
|
||||||
|
|
||||||
|
if (!self)
|
||||||
|
return;
|
||||||
|
|
||||||
onFinishRender();
|
onFinishRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMonitorFrameScheduler::onFinishRender() {
|
void CMonitorFrameScheduler::onFinishRender() {
|
||||||
m_sync = CEGLSync::create(); // this destroys the old sync
|
m_sync = CEGLSync::create(); // this destroys the old sync
|
||||||
g_pEventLoopManager->doOnReadable(m_sync->fd().duplicate(), [this, mon = m_monitor] {
|
g_pEventLoopManager->doOnReadable(m_sync->fd().duplicate(), [this, self = m_self] {
|
||||||
if (!mon) // might've gotten destroyed
|
if (!self) // might've gotten destroyed
|
||||||
return;
|
return;
|
||||||
onSyncFired();
|
onSyncFired();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -22,15 +22,19 @@ class CMonitorFrameScheduler {
|
||||||
void onFrame();
|
void onFrame();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool canRender();
|
bool canRender();
|
||||||
void onFinishRender();
|
void onFinishRender();
|
||||||
bool newSchedulingEnabled();
|
bool newSchedulingEnabled();
|
||||||
|
|
||||||
bool m_renderAtFrame = true;
|
bool m_renderAtFrame = true;
|
||||||
bool m_pendingThird = false;
|
bool m_pendingThird = false;
|
||||||
hrc::time_point m_lastRenderBegun;
|
hrc::time_point m_lastRenderBegun;
|
||||||
|
|
||||||
PHLMONITORREF m_monitor;
|
PHLMONITORREF m_monitor;
|
||||||
|
|
||||||
UP<CEGLSync> m_sync;
|
UP<CEGLSync> m_sync;
|
||||||
|
|
||||||
|
WP<CMonitorFrameScheduler> m_self;
|
||||||
|
|
||||||
|
friend class CMonitor;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue