Merge lp:~nick-dedekind/qtmir/fix-stopSessionWhileSuspending into lp:qtmir

Proposed by Nick Dedekind
Status: Merged
Approved by: Ɓukasz Zemczak
Approved revision: 435
Merged at revision: 435
Proposed branch: lp:~nick-dedekind/qtmir/fix-stopSessionWhileSuspending
Merge into: lp:qtmir
Diff against target: 284 lines (+132/-24)
7 files modified
src/modules/Unity/Application/application.cpp (+14/-5)
src/modules/Unity/Application/application_manager.cpp (+9/-2)
src/modules/Unity/Application/session.cpp (+31/-16)
src/modules/Unity/Application/session.h (+1/-1)
tests/modules/ApplicationManager/application_manager_test.cpp (+37/-0)
tests/modules/SessionManager/session_test.cpp (+37/-0)
tests/modules/common/qtmir_test.cpp (+3/-0)
To merge this branch: bzr merge lp:~nick-dedekind/qtmir/fix-stopSessionWhileSuspending
Reviewer Review Type Date Requested Status
Unity8 CI Bot (community) continuous-integration Needs Fixing
PS Jenkins bot (community) continuous-integration Needs Fixing
Mir development team Pending
Review via email: mp+283655@code.launchpad.net

Commit message

Fixed issue where stopping the session while suspending was causing app close to stall.

Description of the change

Fixed issue where stopping the session while suspending was causing app close to stall.

 * Are there any related MPs required for this MP to build/function as expected? Please list.
No

 * Did you perform an exploratory manual test run of your code change and any related functionality?
Yes

 * If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

FAILED: Continuous integration, rev:435
https://unity8-jenkins.ubuntu.com/job/lp-qtmir-1-ci/33/
Executed test runs:

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtmir-1-ci/33/rebuild

review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/modules/Unity/Application/application.cpp'
2--- src/modules/Unity/Application/application.cpp 2015-12-07 12:23:29 +0000
3+++ src/modules/Unity/Application/application.cpp 2016-01-22 16:33:33 +0000
4@@ -289,6 +289,7 @@
5 return Running;
6 case InternalState::Suspended:
7 return Suspended;
8+ case InternalState::StoppedResumable:
9 case InternalState::Stopped:
10 default:
11 return Stopped;
12@@ -428,7 +429,6 @@
13 // too late
14 break;
15 }
16-
17 }
18
19 void Application::doClose()
20@@ -590,8 +590,12 @@
21 }
22 break;
23 case ProcessSuspended:
24- Q_ASSERT(m_state == InternalState::SuspendingWaitProcess);
25- setInternalState(InternalState::Suspended);
26+ if (m_state == InternalState::Closing) {
27+ // If we get a process suspension event while we're closing, resume the process.
28+ Q_EMIT resumeProcessRequested();
29+ } else {
30+ setInternalState(InternalState::Suspended);
31+ }
32 break;
33 case ProcessFailed:
34 // we assume the session always stop before the process
35@@ -647,7 +651,7 @@
36 {
37 qCDebug(QTMIR_APPLICATIONS) << "Application::resume - appId=" << appId();
38
39- if (m_state == InternalState::Suspended) {
40+ if (m_state == InternalState::Suspended || m_state == InternalState::SuspendingWaitProcess) {
41 setInternalState(InternalState::Running);
42 Q_EMIT resumeProcessRequested();
43 if (m_processState == ProcessSuspended) {
44@@ -761,7 +765,12 @@
45 Q_EMIT suspendProcessRequested();
46 break;
47 case Session::Stopped:
48- if (!canBeResumed()
49+ if ((m_state == InternalState::SuspendingWaitProcess || m_state == InternalState::SuspendingWaitProcess) &&
50+ m_processState != Application::ProcessFailed) {
51+ // Session stopped normally while we're waiting for suspension.
52+ doClose();
53+ Q_EMIT resumeProcessRequested();
54+ } else if (!canBeResumed()
55 || m_state == InternalState::Starting
56 || m_state == InternalState::Running
57 || m_state == InternalState::Closing) {
58
59=== modified file 'src/modules/Unity/Application/application_manager.cpp'
60--- src/modules/Unity/Application/application_manager.cpp 2015-12-07 12:23:29 +0000
61+++ src/modules/Unity/Application/application_manager.cpp 2016-01-22 16:33:33 +0000
62@@ -509,10 +509,17 @@
63
64 void ApplicationManager::onProcessSuspended(const QString &appId)
65 {
66+ qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::onProcessSuspended - appId=" << appId;
67+
68 Application *application = findApplication(appId);
69- if (application) {
70- application->setProcessState(Application::ProcessSuspended);
71+
72+ if (!application) {
73+ qDebug() << "ApplicationManager::onProcessSuspended reports stop of appId=" << appId
74+ << "which AppMan is not managing, ignoring the event";
75+ return;
76 }
77+
78+ application->setProcessState(Application::ProcessSuspended);
79 }
80
81 void ApplicationManager::onFocusRequested(const QString& appId)
82
83=== modified file 'src/modules/Unity/Application/session.cpp'
84--- src/modules/Unity/Application/session.cpp 2015-12-14 17:45:28 +0000
85+++ src/modules/Unity/Application/session.cpp 2016-01-22 16:33:33 +0000
86@@ -108,7 +108,6 @@
87 {
88 Q_ASSERT(m_state == Session::Suspending);
89
90-
91 auto surfaceList = m_surfaces.list();
92 if (surfaceList.empty()) {
93 qCDebug(QTMIR_SESSIONS) << "Application::suspend - no surface to call stopFrameDropper() on!";
94@@ -161,14 +160,34 @@
95 return m_state;
96 }
97
98-void Session::setState(State state) {
99- if (state != m_state) {
100- qCDebug(QTMIR_SESSIONS) << "Session::setState - session=" << name()
101- << "state=" << sessionStateToString(state);
102-
103- m_state = state;
104- Q_EMIT stateChanged(m_state);
105- }
106+void Session::setState(State state)
107+{
108+ if (m_state == state) {
109+ return;
110+ }
111+
112+ qCDebug(QTMIR_SESSIONS) << "Session::setState - session=" << name()
113+ << "state=" << sessionStateToString(state);
114+
115+ if (m_state == Suspending) {
116+ m_suspendTimer->stop();
117+ }
118+
119+ m_state = state;
120+
121+ switch (m_state) {
122+ case Starting:
123+ case Running:
124+ break;
125+ case Suspending:
126+ m_suspendTimer->start(1500);
127+ break;
128+ case Suspended:
129+ case Stopped:
130+ break;
131+ }
132+
133+ Q_EMIT stateChanged(m_state);
134 }
135
136 bool Session::fullscreen() const
137@@ -286,10 +305,7 @@
138
139 void Session::doResume()
140 {
141- if (m_state == Suspending) {
142- Q_ASSERT(m_suspendTimer->isActive());
143- m_suspendTimer->stop();
144- } else if (m_state == Suspended) {
145+ if (m_state == Suspended) {
146 Q_ASSERT(m_surfaces.rowCount() > 0);
147 auto surfaceList = m_surfaces.list();
148 for (int i = 0; i < surfaceList.count(); ++i) {
149@@ -314,6 +330,8 @@
150 {
151 qCDebug(QTMIR_SESSIONS) << "Session::close - " << name();
152
153+ if (m_state == Stopped) return;
154+
155 auto surfaceList = m_surfaces.list();
156 for (int i = 0; i < surfaceList.count(); ++i) {
157 surfaceList[i]->close();
158@@ -328,9 +346,6 @@
159
160 stopPromptSessions();
161
162- if (m_suspendTimer->isActive())
163- m_suspendTimer->stop();
164-
165 {
166 auto surfaceList = m_surfaces.list();
167 for (int i = 0; i < surfaceList.count(); ++i) {
168
169=== modified file 'src/modules/Unity/Application/session.h'
170--- src/modules/Unity/Application/session.h 2015-12-07 12:02:48 +0000
171+++ src/modules/Unity/Application/session.h 2016-01-22 16:33:33 +0000
172@@ -93,7 +93,7 @@
173 private Q_SLOTS:
174 void updateFullscreenProperty();
175
176-private:
177+protected:
178 void setParentSession(Session* session);
179 void setState(State state);
180 void doResume();
181
182=== modified file 'tests/modules/ApplicationManager/application_manager_test.cpp'
183--- tests/modules/ApplicationManager/application_manager_test.cpp 2015-12-07 12:23:29 +0000
184+++ tests/modules/ApplicationManager/application_manager_test.cpp 2016-01-22 16:33:33 +0000
185@@ -2133,3 +2133,40 @@
186 qtApp.exec();
187 EXPECT_EQ(1, spy.count());
188 }
189+
190+/*
191+ * Test that an application that is suspended after its session is stopped is closed
192+ */
193+TEST_F(ApplicationManagerTests,CloseWhenSuspendedAfterSessionStopped)
194+{
195+ using namespace ::testing;
196+
197+ const QString appId("testAppId");
198+ quint64 procId = 5551;
199+
200+ auto application = startApplication(procId, "testAppId");
201+
202+ qtmir::Session* session(static_cast<qtmir::Session*>(application->session()));
203+
204+ FakeMirSurface *surface = new FakeMirSurface;
205+ onSessionCreatedSurface(session->session().get(), surface);
206+ surface->drawFirstFrame();
207+ EXPECT_EQ(Application::InternalState::Running, application->internalState());
208+
209+ // session is suspended
210+ application->setRequestedState(Application::RequestedSuspended);
211+ EXPECT_EQ(Application::InternalState::SuspendingWaitSession, application->internalState());
212+ session->doSuspend();
213+ EXPECT_EQ(Application::InternalState::SuspendingWaitProcess, application->internalState());
214+ session->setLive(false);
215+ EXPECT_EQ(Application::InternalState::Closing, application->internalState());
216+
217+ // The process can be suspended after the session has dissapeared.
218+ applicationManager.onProcessSuspended(application->appId());
219+ EXPECT_EQ(Application::InternalState::Closing, application->internalState());
220+
221+ QSignalSpy spy(application, SIGNAL(stopped()));
222+ applicationManager.onProcessStopped(application->appId());
223+ EXPECT_EQ(Application::Stopped, application->state());
224+ EXPECT_EQ(spy.count(), 1);
225+}
226
227=== modified file 'tests/modules/SessionManager/session_test.cpp'
228--- tests/modules/SessionManager/session_test.cpp 2015-12-07 12:02:48 +0000
229+++ tests/modules/SessionManager/session_test.cpp 2016-01-22 16:33:33 +0000
230@@ -281,3 +281,40 @@
231
232 Mock::VerifyAndClear(mirServer->the_mock_prompt_session_manager().get());
233 }
234+
235+TEST_F(SessionTests, SessionStopsWhileSuspendingDoesntSuspend)
236+{
237+ using namespace testing;
238+
239+ class SessionTestClass : public qtmir::Session
240+ {
241+ public:
242+ SessionTestClass(const std::shared_ptr<mir::scene::Session>& session,
243+ const std::shared_ptr<mir::scene::PromptSessionManager>& promptSessionManager)
244+ : Session(session, promptSessionManager) {}
245+
246+ using Session::m_suspendTimer;
247+ };
248+
249+ const QString appId("test-app");
250+ const pid_t procId = 5551;
251+
252+ auto mirSession = std::make_shared<MockSession>(appId.toStdString(), procId);
253+
254+ auto session = std::make_shared<SessionTestClass>(mirSession, mirServer->the_prompt_session_manager());
255+ {
256+ FakeMirSurface *surface = new FakeMirSurface;
257+ session->registerSurface(surface);
258+ surface->drawFirstFrame();
259+ }
260+ EXPECT_EQ(Session::Running, session->state());
261+
262+ EXPECT_CALL(*mirSession, set_lifecycle_state(mir_lifecycle_state_will_suspend));
263+ session->suspend();
264+ EXPECT_EQ(Session::Suspending, session->state());
265+ EXPECT_TRUE(session->m_suspendTimer->isActive());
266+
267+ session->setLive(false);
268+ EXPECT_EQ(Session::Stopped, session->state());
269+ EXPECT_FALSE(session->m_suspendTimer->isActive());
270+}
271
272=== modified file 'tests/modules/common/qtmir_test.cpp'
273--- tests/modules/common/qtmir_test.cpp 2015-12-03 17:26:31 +0000
274+++ tests/modules/common/qtmir_test.cpp 2016-01-22 16:33:33 +0000
275@@ -41,6 +41,9 @@
276 case Application::InternalState::StoppedResumable:
277 *os << "StoppedResumable";
278 break;
279+ case Application::InternalState::Closing:
280+ *os << "Closing";
281+ break;
282 case Application::InternalState::Stopped:
283 *os << "Stopped";
284 break;

Subscribers

People subscribed via source and target branches