Skip to content

Commit 9b004a7

Browse files
Chris Morinsofar
authored andcommitted
improve list traversal performance and fix fd leaks
1 parent b207ec0 commit 9b004a7

3 files changed

Lines changed: 43 additions & 28 deletions

File tree

src/bootchart.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
#include <stdio.h>
4242
#include <stdlib.h>
4343
#include <string.h>
44-
#include <sys/resource.h>
4544
#include <sys/uio.h>
4645
#include <time.h>
4746
#include <unistd.h>
@@ -323,7 +322,6 @@ int main(int argc, char *argv[]) {
323322
time_t t = 0;
324323
int r, samples;
325324
struct ps_struct *ps;
326-
struct rlimit rlim;
327325
struct list_sample_data *head;
328326
struct sigaction sig = {
329327
.sa_handler = signal_handler,
@@ -351,10 +349,6 @@ int main(int argc, char *argv[]) {
351349
}
352350
argv[0][0] = '@';
353351

354-
rlim.rlim_cur = 4096;
355-
rlim.rlim_max = 4096;
356-
(void) setrlimit(RLIMIT_NOFILE, &rlim);
357-
358352
schfd = open("/proc/sys/kernel/sched_schedstats", O_WRONLY);
359353
if (schfd >= 0) {
360354
write(schfd, "1\n", 2);
@@ -466,8 +460,8 @@ int main(int argc, char *argv[]) {
466460

467461
/* do some cleanup, close fd's */
468462
ps = ps_first;
469-
while (ps->next_ps) {
470-
ps = ps->next_ps;
463+
while (ps->next_running) {
464+
ps = ps->next_running;
471465
ps->schedstat = safe_close(ps->schedstat);
472466
ps->sched = safe_close(ps->sched);
473467
ps->smaps = safe_fclose(ps->smaps);

src/bootchart.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,11 @@ struct list_sample_data {
6262

6363
/* process info */
6464
struct ps_struct {
65-
struct ps_struct *next_ps; /* SLL pointer */
66-
struct ps_struct *parent; /* ppid ref */
67-
struct ps_struct *children; /* children */
68-
struct ps_struct *next; /* siblings */
65+
struct ps_struct *next_ps; /* SLL pointer */
66+
struct ps_struct *next_running; /* currently running */
67+
struct ps_struct *parent; /* ppid ref */
68+
struct ps_struct *children; /* children */
69+
struct ps_struct *next; /* siblings */
6970

7071
/* must match - otherwise it's a new process with same PID */
7172
char name[256];
@@ -78,6 +79,9 @@ struct ps_struct {
7879
int schedstat;
7980
FILE *smaps;
8081

82+
/* used to garbage collect running process list*/
83+
bool still_running;
84+
8185
/* pointers to first/last seen timestamps */
8286
struct ps_sched_struct *first;
8387
struct ps_sched_struct *last;

src/store.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,29 @@ static int pid_cmdline_strscpy(int procfd, char *buffer, size_t buf_len, int pid
9696
return 0;
9797
}
9898

99+
static void garbage_collect_dead_processes(struct ps_struct *ps_first) {
100+
struct ps_struct *ps;
101+
struct ps_struct *ps_next;
102+
103+
ps = ps_first;
104+
while ((ps_next = ps->next_running)) {
105+
if (!ps_next->still_running) {
106+
/* close the stream and fds */
107+
ps_next->schedstat = safe_close(ps_next->schedstat);
108+
ps_next->sched = safe_close(ps_next->sched);
109+
if (ps->smaps)
110+
fclose(ps->smaps);
111+
112+
ps->next_running = ps_next->next_running;
113+
} else {
114+
ps = ps_next;
115+
}
116+
/* this resets the flag for both running and dead processes*/
117+
ps_next->still_running = false;
118+
}
119+
}
120+
121+
99122
int log_sample(DIR *proc,
100123
int sample,
101124
struct ps_struct *ps_first,
@@ -221,8 +244,8 @@ int log_sample(DIR *proc,
221244
continue;
222245

223246
ps = ps_first;
224-
while (ps->next_ps) {
225-
ps = ps->next_ps;
247+
while (ps->next_running) {
248+
ps = ps->next_running;
226249
if (ps->pid == pid)
227250
break;
228251
}
@@ -233,7 +256,7 @@ int log_sample(DIR *proc,
233256
char t[32];
234257
struct ps_struct *parent;
235258

236-
ps->next_ps = new0(struct ps_struct, 1);
259+
ps->next_ps = ps->next_running = new0(struct ps_struct, 1);
237260
if (!ps->next_ps)
238261
return log_oom();
239262

@@ -371,13 +394,8 @@ int log_sample(DIR *proc,
371394
}
372395

373396
s = pread(ps->schedstat, buf, sizeof(buf) - 1, 0);
374-
if (s <= 0) {
375-
/* clean up our file descriptors - assume that the process exited */
376-
close(ps->schedstat);
377-
ps->schedstat = -1;
378-
ps->sched = safe_close(ps->sched);
397+
if (s <= 0)
379398
continue;
380-
}
381399

382400
buf[s] = '\0';
383401

@@ -533,17 +551,13 @@ int log_sample(DIR *proc,
533551
}
534552

535553
s = pread(ps->sched, buf, sizeof(buf) - 1, 0);
536-
if (s <= 0) {
537-
/* clean up file descriptors */
538-
ps->sched = safe_close(ps->sched);
539-
ps->schedstat = safe_close(ps->schedstat);
540-
goto no_sched2;
541-
}
554+
if (s <= 0)
555+
continue;
542556

543557
buf[s] = '\0';
544558

545559
if (!sscanf(buf, "%s %*s %*s", key))
546-
goto no_sched2;
560+
continue;
547561

548562
strscpy(ps->name, sizeof(ps->name), key);
549563

@@ -552,7 +566,10 @@ int log_sample(DIR *proc,
552566
if (arg_show_cmdline)
553567
pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid);
554568
}
569+
ps->still_running = true;
555570
}
556571

572+
garbage_collect_dead_processes(ps_first);
573+
557574
return 0;
558575
}

0 commit comments

Comments
 (0)