Skip to content

Commit 5410c33

Browse files
committed
fix(memory-leak): fix container statistics memory leak (unresolved promise)
1 parent a473225 commit 5410c33

File tree

3 files changed

+35
-43
lines changed

3 files changed

+35
-43
lines changed

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/api/docker-stats.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function getContainersStats(): Observable<any> {
1212
return listContainers()
1313
.then(containers => Promise.all(containers.map(c => getContainerStats(c))));
1414
})
15-
.map(stats => observer.next({ type: 'containersStats', data: stats }))
15+
.map(stats => observer.next({ type: 'containersStats', data: stats.filter(Boolean) }))
1616
.subscribe();
1717

1818
return () => {
@@ -25,14 +25,18 @@ export function getContainersStats(): Observable<any> {
2525

2626
function getContainerStats(container: any): Promise<any> {
2727
return calculateContainerStats(container, processes).then(stats => {
28-
return {
29-
id: stats.id,
30-
name: stats.name,
31-
cpu: getCpuData(stats.data),
32-
network: getNetworkData(stats.data),
33-
memory: getMemory(stats.data),
34-
debug: stats.debug
35-
};
28+
if (stats) {
29+
return {
30+
id: stats.id,
31+
name: stats.name,
32+
cpu: getCpuData(stats.data),
33+
network: getNetworkData(stats.data),
34+
memory: getMemory(stats.data),
35+
debug: stats.debug
36+
};
37+
} else {
38+
return null;
39+
}
3640
});
3741
}
3842

src/api/docker.ts

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import { ProcessOutput } from './process';
88
import * as envVars from './env-variables';
99
import chalk from 'chalk';
1010
import * as style from 'ansi-styles';
11+
import { platform } from 'os';
1112

12-
export let docker = new dockerode();
13+
export const docker = new dockerode();
14+
const binds = platform() === 'darwin' ? [] : ['/var/run/docker.sock:/var/run/docker.sock'];
1315

1416
export function createContainer(
1517
name: string,
@@ -24,7 +26,7 @@ export function createContainer(
2426
OpenStdin: true,
2527
StdinOnce: false,
2628
Env: envVars.serialize(envs) || [],
27-
Binds: ['/var/run/docker.sock:/var/run/docker.sock'],
29+
Binds: binds,
2830
Privileged: true,
2931
ExposedPorts: {
3032
'22/tcp': {},
@@ -290,37 +292,23 @@ export function calculateContainerStats(
290292
container: dockerode.ContainerInfo,
291293
processes: any
292294
): Promise<any> {
293-
return docker.getContainer(container.Id).stats()
294-
.then(stream => {
295-
let json = '';
296-
return new Promise((resolve, reject) => {
297-
stream.on('data', buf => {
298-
let rawJson = json + buf.toString();
299-
try {
300-
let data = JSON.parse(rawJson);
301-
302-
if (data && data.precpu_stats.system_cpu_usage) {
303-
let jobId = container.Names[0].split('_')[2] || -1;
304-
let job = processes.find(p => p.job_id === Number(jobId));
305-
let debug = false;
306-
if (job) {
307-
debug = job.debug || false;
308-
}
309-
310-
let stats = {
311-
id: container.Id,
312-
name: container.Names[0].substr(1) || '',
313-
debug: debug,
314-
data: data
315-
};
295+
return docker.getContainer(container.Id).stats({ stream: false })
296+
.then(stats => {
297+
const data = stats;
298+
if (data && data.precpu_stats.system_cpu_usage) {
299+
const jobId = container.Names[0].split('_')[2] || -1;
300+
const job = processes.find(p => p.job_id === Number(jobId));
301+
const debug = job && job.debug || false;
302+
const stats = {
303+
id: container.Id,
304+
name: container.Names[0].substr(1) || '',
305+
debug: debug,
306+
data: data
307+
};
316308

317-
stream.destroy();
318-
resolve(stats);
319-
}
320-
} catch (e) {
321-
json = rawJson;
322-
}
323-
});
324-
});
309+
return stats;
310+
} else {
311+
return null;
312+
}
325313
});
326314
}

0 commit comments

Comments
 (0)