~mir-team/qtmir/update-surface-observer

« back to all changes in this revision

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

  • Committer: CI bot
  • Author(s): Ted Gould
  • Date: 2014-10-30 21:48:07 UTC
  • mfrom: (252.1.22 ual-pause)
  • Revision ID: ps-jenkins@lists.canonical.com-20141030214807-xmy7xifra09p893o
Use UAL pause/resume functions for stopping/continuing all tasks in the cgroup Fixes: 1379786, 1379788, 1382039
Approved by: Gerry Boland, PS Jenkins bot

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2014 Canonical, Ltd.
3
 
 *
4
 
 * This program is free software: you can redistribute it and/or modify it under
5
 
 * the terms of the GNU Lesser General Public License version 3, as published by
6
 
 * the Free Software Foundation.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 
 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10
 
 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
 
 * Lesser General Public License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU Lesser General Public License
14
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 
 *
16
 
 */
17
 
 
18
 
#include "processcontroller.h"
19
 
 
20
 
#include "logging.h"
21
 
 
22
 
// Process C++
23
 
#include <core/posix/process.h>
24
 
#include <core/posix/this_process.h>
25
 
#include <core/posix/linux/proc/process/oom_adj.h>
26
 
#include <core/posix/linux/proc/process/oom_score_adj.h>
27
 
 
28
 
// std
29
 
#include <signal.h>
30
 
#include <unistd.h>
31
 
 
32
 
/*
33
 
 * ProcessController
34
 
 * This class manages individual processes during their lifetime. It allows one to pause
35
 
 * and resume processes.
36
 
 *
37
 
 * It also has methods to set a score on processes which is used by the Out of Memory (OOM)
38
 
 * process killer to decide what process gets killed in a low memory situation.
39
 
 */
40
 
 
41
 
namespace plpp = core::posix::linux::proc::process;
42
 
 
43
 
namespace qtmir
44
 
{
45
 
 
46
 
ProcessController::OomController::OomController()
47
 
{
48
 
}
49
 
 
50
 
/*!
51
 
 * \brief ProcessController::OomController::ensureProcessLikelyToBeKilled
52
 
 * \param pid
53
 
 * Set the process OOM-killer score so that the process is _more_ likely to be killed
54
 
 * in a low memory situation
55
 
 */
56
 
 
57
 
/*
58
 
 * Useful information about these OOM-weighting methods
59
 
 *
60
 
 * the "Process C++" library wraps some APIs exported by the kernel in the the /proc filesystem.
61
 
 * The OOM score is one of these, but the APIs for it changed from Linux 2.6.36 onward.
62
 
 *
63
 
 * === Up to Linux 2.6.36 ===
64
 
 * /proc/[pid]/oom_adj (wrapped by plpp::OomAdj) was used up to 2.6.36 (is deprecated now)
65
 
 * Valid values are in the range -16 to +15, plus the special value -17, which disables
66
 
 * OOM-killing altogether for this process.  A positive score increases the likelihood
67
 
 * of this process being killed by the OOM-killer; a negative score decreases the likelihood.
68
 
 *
69
 
 * The default value for this file is 0; a new process inherits its parent's oom_adj setting.
70
 
 *
71
 
 * === Linux 2.6.36 and later ===
72
 
 * /proc/[pid]/oom_score_adj (wrapped by plpp::OomScoreAdj) is the recommended API.  Valid
73
 
 * values are in the range -1000 (never kill) to 1000 (always kill).
74
 
 *
75
 
 * For backward compatibility with previous kernels, /proc/[pid]/oom_adj can still be used to
76
 
 * tune the badness score.  Its value is scaled linearly with oom_score_adj. So writing to
77
 
 * /proc/[pid]/oom_score_adj or /proc/[pid]/oom_adj will change the other with its scaled value.
78
 
 *
79
 
 * === How OOM score changing is implemented ===
80
 
 * To support all available kernels, we thus perform the following for any OOM score change:
81
 
 *  1. Attempt to use the newer kernel API (plpp::OomScoreAdj). Fetch the min & max possible
82
 
 *     values and calculate a desired score for the process.
83
 
 *  2. If that fails, fall back to the older kernel API (plpp::OomSAdj), again fetching min
84
 
 *     & max possible values and calculating a desired score for the process.
85
 
 */
86
 
void ProcessController::OomController::ensureProcessLikelyToBeKilled(pid_t pid)
87
 
{
88
 
    // We avoid boundary values for oom_score_adj. For that, we
89
 
    // set it to 80% of the total available range.
90
 
    static const float defaultPercentage = 0.8;
91
 
 
92
 
    core::posix::Process process(pid);
93
 
 
94
 
    try {
95
 
        plpp::OomScoreAdj shellScore;
96
 
        core::posix::this_process::instance() >> shellScore;
97
 
 
98
 
        plpp::OomScoreAdj processScore
99
 
        {
100
 
            static_cast<int>((plpp::OomScoreAdj::max_value() - shellScore.value) * defaultPercentage) + shellScore.value
101
 
        };
102
 
 
103
 
        process << processScore;
104
 
    } catch(...) {
105
 
        // Accessing OomScoreAdj resulted in an exception being thrown.
106
 
        // Trying with the deprecated OomAdj now as a last resort.
107
 
        try
108
 
        {
109
 
            process << plpp::OomAdj{plpp::OomAdj::max_value()};
110
 
        } catch(...)
111
 
        {
112
 
            qDebug() << "ensureProcessIsLikelyToBeKilled failed for pid=" << pid;
113
 
        }
114
 
    }
115
 
}
116
 
 
117
 
/*!
118
 
 * \brief ProcessController::OomController::ensureProcessLessLikelyToBeKilled
119
 
 * \param pid
120
 
 * Set the process OOM-killer score so that, in a low memory situation, the process
121
 
 * is _more_ likely to be killed than the foreground application, but less likely
122
 
 * than the background applications
123
 
 */
124
 
void ProcessController::OomController::ensureProcessLessLikelyToBeKilled(pid_t pid)
125
 
{
126
 
    // Set it to 50% of the total available range.
127
 
    static const float defaultPercentage = 0.5;
128
 
 
129
 
    core::posix::Process process(pid);
130
 
 
131
 
    try {
132
 
        plpp::OomScoreAdj shellScore;
133
 
        core::posix::this_process::instance() >> shellScore;
134
 
 
135
 
        plpp::OomScoreAdj processScore
136
 
        {
137
 
            static_cast<int>((plpp::OomScoreAdj::max_value() - shellScore.value) * defaultPercentage) + shellScore.value
138
 
        };
139
 
 
140
 
        process << processScore;
141
 
    } catch(...) {
142
 
        // Accessing OomScoreAdj resulted in an exception being thrown.
143
 
        // Trying with the deprecated OomAdj now as a last resort.
144
 
        try
145
 
        {
146
 
            process << plpp::OomAdj{plpp::OomAdj::max_value()};
147
 
        } catch(...)
148
 
        {
149
 
            qDebug() << "ensureProcessIsLessLikelyToBeKilled failed for pid=" << pid;
150
 
        }
151
 
    }
152
 
}
153
 
 
154
 
/*!
155
 
 * \brief ProcessController::OomController::ensureProcessUnlikelyToBeKilled
156
 
 * \param pid
157
 
 * Set the process OOM-killer weighting so that the process is _less_ likely to be killed
158
 
 * in a low memory situation
159
 
 */
160
 
void ProcessController::OomController::ensureProcessUnlikelyToBeKilled(pid_t pid)
161
 
{
162
 
    // By system default, we set the oom_score_adj of Unity8 to -10 (via lightdm).
163
 
    // As we want to avoid that any app's oom_score_adj is <= Unity8's oom_score_adj,
164
 
    // (i.e. Unity8 would be killed before that app is) we choose a default increase of +1.
165
 
    static const int default_increase = 1;
166
 
 
167
 
    core::posix::Process process(pid);
168
 
 
169
 
    try {
170
 
        plpp::OomScoreAdj shellScore;
171
 
        core::posix::this_process::instance() >> shellScore;
172
 
 
173
 
        plpp::OomScoreAdj processScore
174
 
        {
175
 
            shellScore.value + default_increase
176
 
        };
177
 
 
178
 
        process << processScore;
179
 
    } catch(...) {
180
 
        // Accessing OomScoreAdj resulted in an exception being thrown.
181
 
        // Trying with the deprecated OomAdj now as a last resort.
182
 
        // By system default, we set the oom_score_adj of Unity8 to -10 (via lightdm).
183
 
        // As we want to avoid that any app's oom_score_adj or oom_adj is <= Unity8's oom_score_adj,
184
 
        // we choose a default value of -9 for oom_score_adj and 0 for oom_adj.
185
 
        static const int defaultValue = 0;
186
 
 
187
 
        try
188
 
        {
189
 
            process << plpp::OomAdj{defaultValue};
190
 
        } catch(...)
191
 
        {
192
 
            qDebug() << "ensureProcessIsUnlikelyToBeKilled failed for pid" << pid;
193
 
        }
194
 
    }
195
 
}
196
 
 
197
 
ProcessController::ProcessController()
198
 
    : m_oomController(new ProcessController::OomController())
199
 
{
200
 
}
201
 
 
202
 
ProcessController::~ProcessController()
203
 
{
204
 
}
205
 
 
206
 
const QSharedPointer<ProcessController::OomController>& ProcessController::oomController() const
207
 
{
208
 
    return m_oomController;
209
 
}
210
 
 
211
 
/*!
212
 
 * \brief ProcessController::sigStopProcessGroupForPid
213
 
 * \param pid
214
 
 * \return True if process was stopped successfully, false otherwise
215
 
 */
216
 
bool ProcessController::sigStopProcessGroupForPid(pid_t pid) const
217
 
{
218
 
    return -1 != kill(-pid, SIGSTOP);
219
 
}
220
 
 
221
 
/*!
222
 
 * \brief ProcessController::sigContinueProcessGroupForPid
223
 
 * \param pid
224
 
 * \return True of process was resumed successfully, false otherwise
225
 
 */
226
 
bool ProcessController::sigContinueProcessGroupForPid(pid_t pid) const
227
 
{
228
 
    return -1 != kill(-pid, SIGCONT);
229
 
}
230
 
 
231
 
} // namespace qtmir