chiark / gitweb /
bootchart: clean up sysfd and proc handling
[elogind.git] / src / bootchart / store.c
index 8e9a62f91d9f9402cdcf14cab0190982f852833d..612510408454439b7974437e4a43c55767a52117 100644 (file)
@@ -45,8 +45,6 @@
  */
 static char smaps_buf[4096];
 static int skip = 0;
-DIR *proc;
-int procfd = -1;
 
 double gettime_ns(void) {
         struct timespec n;
@@ -86,7 +84,7 @@ static char *bufgetline(char *buf) {
         return c;
 }
 
-static int pid_cmdline_strscpy(char *buffer, size_t buf_len, int pid) {
+static int pid_cmdline_strscpy(int procfd, char *buffer, size_t buf_len, int pid) {
         char filename[PATH_MAX];
         _cleanup_close_ int fd=-1;
         ssize_t n;
@@ -107,7 +105,7 @@ static int pid_cmdline_strscpy(char *buffer, size_t buf_len, int pid) {
         return 0;
 }
 
-void log_sample(int sample, struct list_sample_data **ptr) {
+int log_sample(DIR *proc, int sample, struct list_sample_data **ptr) {
         static int vmstat = -1;
         static int schedstat = -1;
         char buf[4096];
@@ -119,41 +117,34 @@ void log_sample(int sample, struct list_sample_data **ptr) {
         int c;
         int p;
         int mod;
-        static int e_fd;
+        static int e_fd = -1;
         ssize_t s;
         ssize_t n;
         struct dirent *ent;
         int fd;
         struct list_sample_data *sampledata;
         struct ps_sched_struct *ps_prev = NULL;
+        int procfd;
 
         sampledata = *ptr;
 
-        /* all the per-process stuff goes here */
-        if (!proc) {
-                /* find all processes */
-                proc = opendir("/proc");
-                if (!proc)
-                        return;
-                procfd = dirfd(proc);
-        } else {
-                rewinddir(proc);
-        }
+        procfd = dirfd(proc);
+        if (procfd < 0)
+                return -errno;
 
         if (vmstat < 0) {
                 /* block stuff */
                 vmstat = openat(procfd, "vmstat", O_RDONLY);
-                if (vmstat == -1) {
-                        log_error_errno(errno, "Failed to open /proc/vmstat: %m");
-                        exit(EXIT_FAILURE);
-                }
+                if (vmstat == -1)
+                        return log_error_errno(errno, "Failed to open /proc/vmstat: %m");
         }
 
         n = pread(vmstat, buf, sizeof(buf) - 1, 0);
         if (n <= 0) {
-                close(vmstat);
-                vmstat = -1;
-                return;
+                vmstat = safe_close(vmstat);
+                if (n < 0)
+                        return -errno;
+                return -ENODATA;
         }
         buf[n] = '\0';
 
@@ -176,17 +167,16 @@ vmstat_next:
         if (schedstat < 0) {
                 /* overall CPU utilization */
                 schedstat = openat(procfd, "schedstat", O_RDONLY);
-                if (schedstat == -1) {
-                        log_error_errno(errno, "Failed to open /proc/schedstat (requires CONFIG_SCHEDSTATS=y in kernel config): %m");
-                        exit(EXIT_FAILURE);
-                }
+                if (schedstat == -1)
+                        return log_error_errno(errno, "Failed to open /proc/schedstat (requires CONFIG_SCHEDSTATS=y in kernel config): %m");
         }
 
         n = pread(schedstat, buf, sizeof(buf) - 1, 0);
         if (n <= 0) {
-                close(schedstat);
-                schedstat = -1;
-                return;
+                schedstat = safe_close(schedstat);
+                if (n < 0)
+                        return -errno;
+                return -ENODATA;
         }
         buf[n] = '\0';
 
@@ -215,16 +205,19 @@ schedstat_next:
         }
 
         if (arg_entropy) {
-                if (!e_fd) {
+                if (e_fd < 0) {
                         e_fd = openat(procfd, "sys/kernel/random/entropy_avail", O_RDONLY);
+                        if (e_fd == -1)
+                                return log_error_errno(errno, "Failed to open /proc/sys/kernel/random/entropy_avail: %m");
                 }
 
-                if (e_fd) {
-                        n = pread(e_fd, buf, sizeof(buf) - 1, 0);
-                        if (n > 0) {
-                                buf[n] = '\0';
-                                sampledata->entropy_avail = atoi(buf);
-                        }
+                n = pread(e_fd, buf, sizeof(buf) - 1, 0);
+                if (n <= 0) {
+                        close(e_fd);
+                        e_fd = -1;
+                } else {
+                        buf[n] = '\0';
+                        sampledata->entropy_avail = atoi(buf);
                 }
         }
 
@@ -256,20 +249,18 @@ schedstat_next:
                         int r;
 
                         ps->next_ps = new0(struct ps_struct, 1);
-                        if (!ps->next_ps) {
-                                log_oom();
-                                exit (EXIT_FAILURE);
-                        }
+                        if (!ps->next_ps)
+                                return log_oom();
+
                         ps = ps->next_ps;
                         ps->pid = pid;
                         ps->sched = -1;
                         ps->schedstat = -1;
 
                         ps->sample = new0(struct ps_sched_struct, 1);
-                        if (!ps->sample) {
-                                log_oom();
-                                exit (EXIT_FAILURE);
-                        }
+                        if (!ps->sample)
+                                return log_oom();
+
                         ps->sample->sampledata = sampledata;
 
                         pscount++;
@@ -302,7 +293,7 @@ schedstat_next:
 
                         /* cmdline */
                         if (arg_show_cmdline)
-                                pid_cmdline_strscpy(ps->name, sizeof(ps->name), pid);
+                                pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid);
 
                         /* discard line 2 */
                         m = bufgetline(buf);
@@ -411,10 +402,9 @@ schedstat_next:
                         continue;
 
                 ps->sample->next = new0(struct ps_sched_struct, 1);
-                if (!ps->sample->next) {
-                        log_oom();
-                        exit(EXIT_FAILURE);
-                }
+                if (!ps->sample->next)
+                        return log_oom();
+
                 ps->sample->next->prev = ps->sample;
                 ps->sample = ps->sample->next;
                 ps->last = ps->sample;
@@ -522,7 +512,9 @@ catch_rename:
 
                         /* cmdline */
                         if (arg_show_cmdline)
-                                pid_cmdline_strscpy(ps->name, sizeof(ps->name), pid);
+                                pid_cmdline_strscpy(procfd, ps->name, sizeof(ps->name), pid);
                 }
         }
+
+        return 0;
 }