]> granicus.if.org Git - procps-ng/commitdiff
library: make reads & unref logic a little more robust
authorJim Warner <james.warner@comcast.net>
Sun, 28 Jun 2015 05:00:00 +0000 (00:00 -0500)
committerCraig Small <csmall@enc.com.au>
Mon, 29 Jun 2015 11:30:48 +0000 (21:30 +1000)
Since we are not using a higher level standard C fopen
all of the read requests were made signal sensitive as
that can result in a 'temporarily' failed i/o request.

Also, protection against some user calling the 'unref'
function on already free memory has been incorporated.
This will protect us from some nasty 'Abort' surprise.

Signed-off-by: Jim Warner <james.warner@comcast.net>
proc/meminfo.c
proc/readstat.c
proc/vmstat.c

index 7ab1cc9e8d9d0c4d90c060828d4a5dd853f5a16a..6cfe808c3c0a540f9ef9c68a68e30028e3cddd49 100644 (file)
@@ -110,9 +110,16 @@ PROCPS_EXPORT int procps_meminfo_read (
     if (lseek(info->meminfo_fd, 0L, SEEK_SET) == -1) {
         return -errno;
     }
-    if ((size = read(info->meminfo_fd, buf, sizeof(buf)-1)) < 0) {
-        return -1;
+    for (;;) {
+        if ((size = read(info->meminfo_fd, buf, sizeof(buf)-1)) < 0) {
+            if (errno == EINTR || errno == EAGAIN)
+                continue;
+            return -errno;
+        }
+        break;
     }
+    if (size == 0)
+        return 0;
     buf[size] = '\0';
 
     /* Scan the file */
@@ -219,11 +226,11 @@ PROCPS_EXPORT struct procps_meminfo *procps_meminfo_ref (
 PROCPS_EXPORT struct procps_meminfo *procps_meminfo_unref (
         struct procps_meminfo *info)
 {
-    if (info == NULL)
+    if (info == NULL || info->refcount == 0)
         return NULL;
     info->refcount--;
     if (info->refcount > 0)
-        return NULL;
+        return info;
     free(info);
     return NULL;
 }
index c8873e77096a5a57cbd31846daf0244fa7a95a1f..16322ad3b62eb8146d93592b09db3e36d79dc85d 100644 (file)
@@ -90,9 +90,16 @@ PROCPS_EXPORT int procps_stat_read (
     if (lseek(info->stat_fd, 0L, SEEK_SET) == -1) {
         return -errno;
     }
-    if ((size = read(info->stat_fd, buf, sizeof(buf)-1)) < 0) {
-        return -1;
+    for (;;) {
+        if ((size = read(info->stat_fd, buf, sizeof(buf)-1)) < 0) {
+            if (errno == EINTR || errno == EAGAIN)
+                continue;
+            return -errno;
+        }
+        break;
     }
+    if (size == 0)
+        return 0;
     buf[size] = '\0';
 
     /* Scan the file */
@@ -155,11 +162,11 @@ PROCPS_EXPORT struct procps_statinfo *procps_stat_ref (
 PROCPS_EXPORT struct procps_statinfo *procps_stat_unref (
         struct procps_statinfo *info)
 {
-    if (info == NULL)
+    if (info == NULL || info->refcount == 0)
         return NULL;
     info->refcount--;
     if (info->refcount > 0)
-        return NULL;
+        return info;
     free(info);
     return NULL;
 }
index 8f9f1f6f376295e66b6b314a4ad7cbf1068e489d..953c8b6a074be43b63b27dcb912d5ad9863ef8cc 100644 (file)
@@ -83,9 +83,16 @@ PROCPS_EXPORT int procps_vmstat_read (
     if (lseek(info->vmstat_fd, 0L, SEEK_SET) == -1) {
         return -errno;
     }
-    if ((size = read(info->vmstat_fd, buf, sizeof(buf)-1)) < 0) {
-        return -1;
+    for (;;) {
+        if ((size = read(info->vmstat_fd, buf, sizeof(buf)-1)) < 0) {
+            if (errno == EINTR || errno == EAGAIN)
+                continue;
+            return -errno;
+        }
+        break;
     }
+    if (size == 0)
+        return 0;
     buf[size] = '\0';
 
     /* Scan the file */
@@ -130,11 +137,11 @@ PROCPS_EXPORT struct procps_vmstat *procps_vmstat_ref (
 PROCPS_EXPORT struct procps_vmstat *procps_vmstat_unref (
         struct procps_vmstat *info)
 {
-    if (info == NULL)
+    if (info == NULL || info->refcount == 0)
         return NULL;
     info->refcount--;
     if (info->refcount > 0)
-        return NULL;
+        return info;
     free(info);
     return NULL;
 }