1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | 'use strict';
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 | var p = require('path');
|
14 | var treekill = require('../TreeKill');
|
15 | var cst = require('../../constants.js');
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | module.exports = function(God) {
|
24 |
|
25 | |
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 | God.logAndGenerateError = function(err) {
|
32 |
|
33 | if (err instanceof Error) {
|
34 | console.trace(err);
|
35 | return err;
|
36 | }
|
37 |
|
38 | console.error(err);
|
39 | return new Error(err);
|
40 | };
|
41 |
|
42 | |
43 |
|
44 |
|
45 |
|
46 |
|
47 | God.getProcesses = function() {
|
48 | return God.clusters_db;
|
49 | };
|
50 |
|
51 | God.getFormatedProcess = function getFormatedProcesses(id) {
|
52 | if (God.clusters_db[id])
|
53 | return {
|
54 | pid : God.clusters_db[id].process.pid,
|
55 | name : God.clusters_db[id].pm2_env.name,
|
56 | pm2_env : God.clusters_db[id].pm2_env,
|
57 | pm_id : God.clusters_db[id].pm2_env.pm_id
|
58 | };
|
59 | return {};
|
60 | };
|
61 |
|
62 | |
63 |
|
64 |
|
65 |
|
66 |
|
67 | God.getFormatedProcesses = function getFormatedProcesses() {
|
68 | var keys = Object.keys(God.clusters_db);
|
69 | var arr = new Array();
|
70 | var kl = keys.length;
|
71 |
|
72 | for (var i = 0; i < kl; i++) {
|
73 | var key = keys[i];
|
74 |
|
75 | if (!God.clusters_db[key]) continue;
|
76 |
|
77 | if (isNaN(God.clusters_db[key].pm2_env.pm_id)) continue;
|
78 |
|
79 | arr.push({
|
80 | pid : God.clusters_db[key].process.pid,
|
81 | name : God.clusters_db[key].pm2_env.name,
|
82 | pm2_env : God.clusters_db[key].pm2_env,
|
83 | pm_id : God.clusters_db[key].pm2_env.pm_id
|
84 | })
|
85 | }
|
86 | return arr;
|
87 | };
|
88 |
|
89 | |
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 | God.findProcessById = function findProcessById(id) {
|
96 | return God.clusters_db[id] ? God.clusters_db[id] : null;
|
97 | };
|
98 |
|
99 | |
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 | God.findByName = function(name) {
|
106 | var db = God.clusters_db;
|
107 | var arr = [];
|
108 |
|
109 | if (name == 'all') {
|
110 | for (var key in db) {
|
111 |
|
112 | if (typeof(God.clusters_db[key].pm2_env.pm_id) === 'number')
|
113 | arr.push(db[key]);
|
114 | }
|
115 | return arr;
|
116 | }
|
117 |
|
118 | for (var key in db) {
|
119 | if (God.clusters_db[key].pm2_env.name == name ||
|
120 | God.clusters_db[key].pm2_env.pm_exec_path == p.resolve(name)) {
|
121 | arr.push(db[key]);
|
122 | }
|
123 | }
|
124 | return arr;
|
125 | };
|
126 |
|
127 | |
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 | God.checkProcess = function(pid) {
|
135 | if (!pid) return false;
|
136 |
|
137 | try {
|
138 |
|
139 | process.kill(pid, 0);
|
140 | return true;
|
141 | }
|
142 | catch (err) {
|
143 | return false;
|
144 | }
|
145 | };
|
146 |
|
147 | |
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 | God.processIsDead = function(pid, pm2_env, cb, sigkill) {
|
155 | if (!pid) return cb({type : 'param:missing', msg : 'no pid passed'});
|
156 |
|
157 | var timeout = null;
|
158 | var kill_timeout = (pm2_env && pm2_env.kill_timeout) ? pm2_env.kill_timeout : cst.KILL_TIMEOUT;
|
159 | var mode = pm2_env.exec_mode;
|
160 |
|
161 | var timer = setInterval(function() {
|
162 | if (God.checkProcess(pid) === false) {
|
163 | console.log('pid=%d msg=process killed', pid);
|
164 | clearTimeout(timeout);
|
165 | clearInterval(timer);
|
166 | return cb(null, true);
|
167 | }
|
168 | console.log('pid=%d msg=failed to kill - retrying in %dms', pid, pm2_env.kill_retry_time);
|
169 | return false;
|
170 | }, pm2_env.kill_retry_time);
|
171 |
|
172 | timeout = setTimeout(function() {
|
173 | clearInterval(timer);
|
174 | if (sigkill) {
|
175 | console.log('Process with pid %d could not be killed', pid);
|
176 | return cb({type : 'timeout', msg : 'timeout'});
|
177 | }
|
178 | else {
|
179 | console.log('Process with pid %d still alive after %sms, sending it SIGKILL now...', pid, kill_timeout);
|
180 |
|
181 | if (pm2_env.treekill !== true) {
|
182 | try {
|
183 | process.kill(parseInt(pid), 'SIGKILL');
|
184 | } catch(e) {
|
185 | console.error('[SimpleKill][SIGKILL] %s pid can not be killed', pid, e.stack, e.message);
|
186 | }
|
187 | return God.processIsDead(pid, pm2_env, cb, true);
|
188 | }
|
189 | else {
|
190 | treekill(parseInt(pid), 'SIGKILL', function(err) {
|
191 | return God.processIsDead(pid, pm2_env, cb, true);
|
192 | });
|
193 | }
|
194 | }
|
195 | }, kill_timeout);
|
196 | return false;
|
197 | };
|
198 |
|
199 | |
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 | God.killProcess = function(pid, pm2_env, cb) {
|
208 | if (!pid) return cb({msg : 'no pid passed or null'});
|
209 |
|
210 | if (typeof(pm2_env.pm_id) === 'number' &&
|
211 | (cst.KILL_USE_MESSAGE || pm2_env.shutdown_with_message == true)) {
|
212 | var proc = God.clusters_db[pm2_env.pm_id];
|
213 |
|
214 | if (proc && proc.send) {
|
215 | try {
|
216 | proc.send('shutdown');
|
217 | } catch (e) {
|
218 | console.error(`[AppKill] Cannot send "shutdown" message to ${pid}`)
|
219 | console.error(e.stack, e.message)
|
220 | }
|
221 | return God.processIsDead(pid, pm2_env, cb);
|
222 | }
|
223 | else {
|
224 | console.log(`[AppKill] ${pid} pid cannot be notified with send()`)
|
225 | }
|
226 | }
|
227 |
|
228 | if (pm2_env.treekill !== true) {
|
229 | try {
|
230 | process.kill(parseInt(pid), cst.KILL_SIGNAL);
|
231 | } catch(e) {
|
232 | console.error('[SimpleKill] %s pid can not be killed', pid, e.stack, e.message);
|
233 | }
|
234 | return God.processIsDead(pid, pm2_env, cb);
|
235 | }
|
236 | else {
|
237 | treekill(parseInt(pid), cst.KILL_SIGNAL, function(err) {
|
238 | return God.processIsDead(pid, pm2_env, cb);
|
239 | });
|
240 | }
|
241 | };
|
242 |
|
243 | |
244 |
|
245 |
|
246 |
|
247 |
|
248 | God.getNewId = function() {
|
249 | return God.next_id++;
|
250 | };
|
251 |
|
252 | |
253 |
|
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 | God.resetState = function(pm2_env) {
|
260 | pm2_env.created_at = Date.now();
|
261 | pm2_env.unstable_restarts = 0;
|
262 | pm2_env.prev_restart_delay = 0;
|
263 | };
|
264 |
|
265 | };
|