~aacid/qtmir/fix_leaks_application_manager_test

« back to all changes in this revision

Viewing changes to src/modules/Unity/Application/application.cpp

  • Committer: CI Train Bot
  • Author(s): Daniel d'Andrada
  • Date: 2016-05-20 08:41:17 UTC
  • mfrom: (482.2.2 bogusRespawn-lp1575577)
  • Revision ID: ci-train-bot@canonical.com-20160520084117-uj7qmbt7dd1mwdnk
Application: Don't respawn if closed while still starting up

+ refactoring of Application::onSessionStateChanged to explicitly cover every single internal state on session stopping. Fixes: #1575577
Approved by: Gerry Boland, Unity8 CI Bot, Michael Terry

Show diffs side-by-side

added added

removed removed

Lines of Context:
427
427
    return m_session ? m_session->fullscreen() : false;
428
428
}
429
429
 
430
 
bool Application::canBeResumed() const
431
 
{
432
 
    return m_processState != ProcessUnknown;
433
 
}
434
 
 
435
430
pid_t Application::pid() const
436
431
{
437
432
    return m_pid;
776
771
        Q_EMIT suspendProcessRequested();
777
772
        break;
778
773
    case Session::Stopped:
779
 
        if ((m_state == InternalState::SuspendingWaitSession || m_state == InternalState::SuspendingWaitProcess)
780
 
                && m_processState != Application::ProcessFailed) {
781
 
            // Session stopped normally while we're waiting for suspension
 
774
        onSessionStopped();
 
775
    }
 
776
}
 
777
 
 
778
void Application::onSessionStopped()
 
779
{
 
780
    switch (m_state) {
 
781
    case InternalState::Starting:
 
782
        /* application has stopped before it managed to create a surface, we can
 
783
           assume it crashed on startup, and thus cannot be resumed */
 
784
        setInternalState(InternalState::Stopped);
 
785
        break;
 
786
    case InternalState::Running:
 
787
        /* application is on foreground, if Mir reports the application disconnects,
 
788
           it either crashed or stopped itself. Either way, it must go away. */
 
789
        setInternalState(InternalState::Stopped);
 
790
        break;
 
791
    case InternalState::RunningInBackground:
 
792
        if (m_processState == Application::ProcessFailed) {
 
793
            /* killed by the Out-Of-Memory killer while in background. Keep it in the window list
 
794
               as the user didn't want it to go away */
 
795
            setInternalState(InternalState::StoppedResumable);
 
796
        } else {
 
797
            /* the application closed itself while in the background. Let it go away */
 
798
            setInternalState(InternalState::Stopped);
 
799
        }
 
800
        break;
 
801
    case InternalState::SuspendingWaitSession:
 
802
    case InternalState::SuspendingWaitProcess:
 
803
        if (m_processState == Application::ProcessFailed) {
 
804
            /* killed by the Out-Of-Memory killer while suspended (or getting there), keep it around as the user
 
805
               doesn't expect it to disappear */
 
806
            setInternalState(InternalState::StoppedResumable);
 
807
        } else {
 
808
            /* Session stopped normally while we're waiting for suspension */
782
809
            stop();
783
810
            setInternalState(InternalState::Stopped);
784
 
        } else if (!canBeResumed()
785
 
                || m_state == InternalState::Starting
786
 
                || m_state == InternalState::Running
787
 
                || m_state == InternalState::Closing) {
788
 
            /*  1. application is not managed by upstart
789
 
             *  2. application is managed by upstart, but has stopped before it managed
790
 
             *     to create a surface, we can assume it crashed on startup, and thus
791
 
             *     cannot be resumed
792
 
             *  3. application is managed by upstart and is in foreground (i.e. has
793
 
             *     Running state), if Mir reports the application disconnects, it
794
 
             *     either crashed or stopped itself.
795
 
             *  4. We're expecting the application to stop after a close request
796
 
             */
797
 
            setInternalState(InternalState::Stopped);
 
811
        }
 
812
        break;
 
813
    case InternalState::Suspended:
 
814
        if (m_processState != ProcessUnknown) {
 
815
            /* If the user explicly closed this application, we would have it resumed before doing so.
 
816
               Since this is not the case, keep it around. */
 
817
            setInternalState(InternalState::StoppedResumable);
798
818
        } else {
799
 
            setInternalState(InternalState::StoppedResumable);
 
819
            /* We're not able to respawn this application because it's not managed by upstart
 
820
               (probably was launched via cmd line by user) */
 
821
            setInternalState(InternalState::Stopped);
800
822
        }
 
823
        break;
 
824
    case InternalState::Closing:
 
825
        /* We're expecting the application to stop after a close request */
 
826
        setInternalState(InternalState::Stopped);
 
827
        break;
 
828
    case InternalState::StoppedResumable:
 
829
    case InternalState::Stopped:
 
830
        /* NOOP */
 
831
        break;
801
832
    }
802
833
}
803
834