]> granicus.if.org Git - procps-ng/commitdiff
library: refine support for multiple concurrent access
authorJim Warner <james.warner@comcast.net>
Wed, 10 Nov 2021 05:00:00 +0000 (00:00 -0500)
committerCraig Small <csmall@dropbear.xyz>
Sun, 14 Nov 2021 05:23:07 +0000 (16:23 +1100)
Our new library's now well protected against potential
problems which arise when a multi-threaded application
opens more than one context within the same API at the
same time. However, with a single-threaded application
designed along those same lines, some problems remain.

So, to avoid potential corruption of some data (which
was classified as local 'static __thread') from those
single-threaded designs, we'll move several variables
to the info structure itself and remove the '__thread'
qualifier. Now they're protected against both designs.

[ we'll not be protected against some multi-threaded ]
[ application that shares a single context yet calls ]
[ that interface from separate threads. this is just ]
[ bad application design & no different than sharing ]
[ other modifiable global data between such threads! ]

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

index 705e512223338c0ace198b818adcb0e50c4cde5e..79e7fe19295a55cd6713e07d11cf0ecf829be64e 100644 (file)
@@ -135,6 +135,7 @@ struct meminfo_info {
     struct stacks_extent *extents;
     struct hsearch_data hashtab;
     struct meminfo_result get_this;
+    time_t sav_secs;
 };
 
 
@@ -882,7 +883,6 @@ PROCPS_EXPORT struct meminfo_result *procps_meminfo_get (
         struct meminfo_info *info,
         enum meminfo_item item)
 {
-    static __thread time_t sav_secs;
     time_t cur_secs;
 
     errno = EINVAL;
@@ -895,10 +895,10 @@ PROCPS_EXPORT struct meminfo_result *procps_meminfo_get (
     /* we will NOT read the meminfo file with every call - rather, we'll offer
        a granularity of 1 second between reads ... */
     cur_secs = time(NULL);
-    if (1 <= cur_secs - sav_secs) {
+    if (1 <= cur_secs - info->sav_secs) {
         if (meminfo_read_failed(info))
             return NULL;
-        sav_secs = cur_secs;
+        info->sav_secs = cur_secs;
     }
 
     info->get_this.item = item;
index 778f2a90a1a419b7b2b65cbbff7fd6dcae3a7d12..f932ae513b81584f8ee4d92236361b07f016415b 100644 (file)
@@ -96,6 +96,8 @@ struct pids_info {
     struct stacks_extent *get_ext;     // for active 'get' (also within 'extents')
     enum pids_fetch_type get_type;     // last known type of 'get' request
     int seterr;                        // an ENOMEM encountered during assign
+    proc_t get_proc;                   // the proc_t used by procps_pids_get
+    proc_t fetch_proc;                 // the proc_t used by pids_stacks_fetch
 };
 
 
@@ -1123,7 +1125,6 @@ static int pids_stacks_fetch (
  #define n_alloc  info->fetch.n_alloc
  #define n_inuse  info->fetch.n_inuse
  #define n_saved  info->fetch.n_alloc_save
-    static __thread proc_t task;  // static for initial 0's + later free(s)
     struct stacks_extent *ext;
 
     // initialize stuff -----------------------------------
@@ -1140,7 +1141,7 @@ static int pids_stacks_fetch (
 
     // iterate stuff --------------------------------------
     n_inuse = 0;
-    while (info->read_something(info->fetch_PT, &task)) {
+    while (info->read_something(info->fetch_PT, &info->fetch_proc)) {
         if (!(n_inuse < n_alloc)) {
             n_alloc += STACKS_GROW;
             if (!(info->fetch.anchor = realloc(info->fetch.anchor, sizeof(void *) * n_alloc))
@@ -1148,9 +1149,9 @@ static int pids_stacks_fetch (
                 return -1;   // here, errno was set to ENOMEM
             memcpy(info->fetch.anchor + n_inuse, ext->stacks, sizeof(void *) * STACKS_GROW);
         }
-        if (!pids_proc_tally(info, &info->fetch.counts, &task))
+        if (!pids_proc_tally(info, &info->fetch.counts, &info->fetch_proc))
             return -1;       // here, errno was set to ENOMEM
-        if (!pids_assign_results(info, info->fetch.anchor[n_inuse++], &task))
+        if (!pids_assign_results(info, info->fetch.anchor[n_inuse++], &info->fetch_proc))
             return -1;       // here, errno was set to ENOMEM
     }
     /* while the possibility is extremely remote, the readproc.c (read_something) |
@@ -1404,7 +1405,6 @@ PROCPS_EXPORT struct pids_stack *procps_pids_get (
         struct pids_info *info,
         enum pids_fetch_type which)
 {
-    static __thread proc_t task;  // static for initial 0's + later free(s)
 
     errno = EINVAL;
     if (info == NULL)
@@ -1432,9 +1432,9 @@ fresh_start:
     }
     errno = 0;
 
-    if (NULL == info->read_something(info->get_PT, &task))
+    if (NULL == info->read_something(info->get_PT, &info->get_proc))
         return NULL;
-    if (!pids_assign_results(info, info->get_ext->stacks[0], &task))
+    if (!pids_assign_results(info, info->get_ext->stacks[0], &info->get_proc))
         return NULL;
     return info->get_ext->stacks[0];
 } // end: procps_pids_get
index 59e4000eee624ab29c362c21a84db9c31f90a19c..bc048eef25b778600cba71479c03dbbd91e747a8 100644 (file)
@@ -133,6 +133,7 @@ struct slabinfo_info {
     struct fetch_support fetch;      // support for procps_slabinfo_reap
     struct slabs_node nul_node;      // used by slabinfo_get/select
     struct slabinfo_result get_this; // used by slabinfo_get
+    time_t sav_secs;                 // used by slabinfo_get
 };
 
 
@@ -839,7 +840,6 @@ PROCPS_EXPORT struct slabinfo_result *procps_slabinfo_get (
         struct slabinfo_info *info,
         enum slabinfo_item item)
 {
-    static __thread time_t sav_secs;
     time_t cur_secs;
 
     errno = EINVAL;
@@ -852,10 +852,10 @@ PROCPS_EXPORT struct slabinfo_result *procps_slabinfo_get (
     /* we will NOT read the slabinfo file with every call - rather, we'll offer
        a granularity of 1 second between reads ... */
     cur_secs = time(NULL);
-    if (1 <= cur_secs - sav_secs) {
+    if (1 <= cur_secs - info->sav_secs) {
         if (slabinfo_read_failed(info))
             return NULL;
-        sav_secs = cur_secs;
+        info->sav_secs = cur_secs;
     }
 
     info->get_this.item = item;
index e2ec4a3acc5e2327fa43b7013ff7b835b6a82c67..8ce6f5c7a5c1ba21533292a09fad4808856906b3 100644 (file)
@@ -145,6 +145,7 @@ struct stat_info {
     struct stat_result get_this;       // for return to caller after a get
     struct item_support reap_items;    // items used for reap (shared among 3)
     struct item_support select_items;  // items unique to select
+    time_t sav_secs;                   // used by procps_stat_get to limit i/o
 };
 
 
@@ -990,7 +991,6 @@ PROCPS_EXPORT struct stat_result *procps_stat_get (
         struct stat_info *info,
         enum stat_item item)
 {
-    static __thread time_t sav_secs;
     time_t cur_secs;
 
     errno = EINVAL;
@@ -1003,10 +1003,10 @@ PROCPS_EXPORT struct stat_result *procps_stat_get (
     /* we will NOT read the source file with every call - rather, we'll offer
        a granularity of 1 second between reads ... */
     cur_secs = time(NULL);
-    if (1 <= cur_secs - sav_secs) {
+    if (1 <= cur_secs - info->sav_secs) {
         if (stat_read_failed(info))
             return NULL;
-        sav_secs = cur_secs;
+        info->sav_secs = cur_secs;
     }
 
     info->get_this.item = item;
index 9281cefab23c04354a89a10f777bf319690c12d4..7256cf09506449fdf39584f3f711414bb8049633 100644 (file)
@@ -236,6 +236,7 @@ struct vmstat_info {
     struct stacks_extent *extents;
     struct hsearch_data hashtab;
     struct vmstat_result get_this;
+    time_t sav_secs;
 };
 
 
@@ -1376,7 +1377,6 @@ PROCPS_EXPORT struct vmstat_result *procps_vmstat_get (
         struct vmstat_info *info,
         enum vmstat_item item)
 {
-    static __thread time_t sav_secs;
     time_t cur_secs;
 
     errno = EINVAL;
@@ -1389,10 +1389,10 @@ PROCPS_EXPORT struct vmstat_result *procps_vmstat_get (
     /* we will NOT read the vmstat file with every call - rather, we'll offer
        a granularity of 1 second between reads ... */
     cur_secs = time(NULL);
-    if (1 <= cur_secs - sav_secs) {
+    if (1 <= cur_secs - info->sav_secs) {
         if (vmstat_read_failed(info))
             return NULL;
-        sav_secs = cur_secs;
+        info->sav_secs = cur_secs;
     }
 
     info->get_this.item = item;