library: ensure thread safety via function substitutes
Even though we we had to abandon the master branch top multi-thread effort and even though the newlib version of a multi-threaded top provides no real benefit, that whole exercise was not wasted. Rather, it has revealed some deficiencies in our library which this addresses. If two or more threads in the same address space tried to use procps_loadavg or procps_uptime simultaneously, there's a chance they would experience problems due to thread-unsafe functions our library called internally. So, this patch switches them for thread-safe versions. [ along the way we will also make that procps_uptime ] [ initialization of his 'up' & 'idle' variables mean ] [ something by delaying the -ERANGE return a little. ] Reference(s): https://www.freelists.org/post/procps/a-few-more-patches,7 Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
parent
23cfb71366
commit
ca30741a30
@ -124,17 +124,17 @@ PROCPS_EXPORT int procps_loadavg(
|
|||||||
double *restrict av15)
|
double *restrict av15)
|
||||||
{
|
{
|
||||||
double avg_1=0, avg_5=0, avg_15=0;
|
double avg_1=0, avg_5=0, avg_15=0;
|
||||||
char savelocale[128];
|
locale_t tmplocale;
|
||||||
int retval=0;
|
int retval=0;
|
||||||
|
|
||||||
FILE_TO_BUF(LOADAVG_FILE,loadavg_fd);
|
FILE_TO_BUF(LOADAVG_FILE,loadavg_fd);
|
||||||
snprintf(savelocale, sizeof(savelocale), "%s", setlocale(LC_NUMERIC, NULL));
|
tmplocale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
|
||||||
setlocale(LC_NUMERIC, "C");
|
uselocale(tmplocale);
|
||||||
if (sscanf(buf, "%lf %lf %lf", &avg_1, &avg_5, &avg_15) < 3) {
|
if (sscanf(buf, "%lf %lf %lf", &avg_1, &avg_5, &avg_15) < 3)
|
||||||
setlocale(LC_NUMERIC, savelocale);
|
|
||||||
retval = -ERANGE;
|
retval = -ERANGE;
|
||||||
}
|
|
||||||
setlocale(LC_NUMERIC, savelocale);
|
uselocale(LC_GLOBAL_LOCALE);
|
||||||
|
freelocale(tmplocale);
|
||||||
SET_IF_DESIRED(av1, avg_1);
|
SET_IF_DESIRED(av1, avg_1);
|
||||||
SET_IF_DESIRED(av5, avg_5);
|
SET_IF_DESIRED(av5, avg_5);
|
||||||
SET_IF_DESIRED(av15, avg_15);
|
SET_IF_DESIRED(av15, avg_15);
|
||||||
|
@ -69,25 +69,27 @@ PROCPS_EXPORT int procps_uptime(
|
|||||||
double *restrict idle_secs)
|
double *restrict idle_secs)
|
||||||
{
|
{
|
||||||
double up=0, idle=0;
|
double up=0, idle=0;
|
||||||
char savelocale[128];
|
locale_t tmplocale;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if ((fp = fopen(UPTIME_FILE, "r")) == NULL)
|
if ((fp = fopen(UPTIME_FILE, "r")) == NULL)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
snprintf(savelocale, sizeof(savelocale), "%s", setlocale(LC_NUMERIC, NULL));
|
tmplocale = newlocale(LC_NUMERIC_MASK, "C", (locale_t)0);
|
||||||
setlocale(LC_NUMERIC, "C");
|
uselocale(tmplocale);
|
||||||
if (fscanf(fp, "%lf %lf", &up, &idle) < 2) {
|
rc = fscanf(fp, "%lf %lf", &up, &idle);
|
||||||
setlocale(LC_NUMERIC, savelocale);
|
|
||||||
fclose(fp);
|
|
||||||
return -ERANGE;
|
|
||||||
}
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
setlocale(LC_NUMERIC, savelocale);
|
uselocale(LC_GLOBAL_LOCALE);
|
||||||
|
freelocale(tmplocale);
|
||||||
|
|
||||||
if (uptime_secs)
|
if (uptime_secs)
|
||||||
*uptime_secs = up;
|
*uptime_secs = up;
|
||||||
if (idle_secs)
|
if (idle_secs)
|
||||||
*idle_secs = idle;
|
*idle_secs = idle;
|
||||||
|
|
||||||
|
if (rc < 2)
|
||||||
|
return -ERANGE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,14 +105,15 @@ PROCPS_EXPORT char *procps_uptime_sprint(void)
|
|||||||
int upminutes, uphours, updays, users;
|
int upminutes, uphours, updays, users;
|
||||||
int pos;
|
int pos;
|
||||||
time_t realseconds;
|
time_t realseconds;
|
||||||
struct tm *realtime;
|
struct tm realtime;
|
||||||
double uptime_secs, idle_secs;
|
double uptime_secs, idle_secs;
|
||||||
double av1, av5, av15;
|
double av1, av5, av15;
|
||||||
|
|
||||||
upbuf[0] = '\0';
|
upbuf[0] = '\0';
|
||||||
if (time(&realseconds) < 0)
|
if (time(&realseconds) < 0)
|
||||||
return upbuf;
|
return upbuf;
|
||||||
realtime = localtime(&realseconds);
|
localtime_r(&realseconds, &realtime);
|
||||||
|
|
||||||
if (procps_uptime(&uptime_secs, &idle_secs) < 0)
|
if (procps_uptime(&uptime_secs, &idle_secs) < 0)
|
||||||
return upbuf;
|
return upbuf;
|
||||||
|
|
||||||
@ -119,7 +122,7 @@ PROCPS_EXPORT char *procps_uptime_sprint(void)
|
|||||||
upminutes = ((int) uptime_secs / (60)) % 60;
|
upminutes = ((int) uptime_secs / (60)) % 60;
|
||||||
|
|
||||||
pos = sprintf(upbuf, " %02d:%02d:%02d up ",
|
pos = sprintf(upbuf, " %02d:%02d:%02d up ",
|
||||||
realtime->tm_hour, realtime->tm_min, realtime->tm_sec);
|
realtime.tm_hour, realtime.tm_min, realtime.tm_sec);
|
||||||
|
|
||||||
if (updays)
|
if (updays)
|
||||||
pos += sprintf(upbuf + pos, "%d %s, ", updays, (updays > 1) ? "days" : "day");
|
pos += sprintf(upbuf + pos, "%d %s, ", updays, (updays > 1) ? "days" : "day");
|
||||||
|
Loading…
Reference in New Issue
Block a user