linux: fix cpu count
When libuv is running inside container - eg. lxc container, cpu number is not obvious. Linux control groups (cgroups) may limit numer of cpus. As a result of different number cpu cores inside container and outside container, libuv is crashing. sysconf(_SC_NPROCESSORS_ONLN) - returns num of host cpus (eg. 32) `/proc/stat` - sees only cpus limited by cgroups (eg. 4) When libuv is trying to operate at both numbers and they're different it's crashing with current test: run-tests: ../src/unix/linux-core.c:766: read_times: Assertion `num == numcpus' failed. Count the number of cpus based on `/proc/stat` instead. PR-URL: https://github.com/libuv/libuv/pull/735 Reviewed-By: Saúl Ibarra Corretgé <saghul@gmail.com>
This commit is contained in:
parent
ca0b657891
commit
6798876a6b
@ -69,7 +69,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int read_models(unsigned int numcpus, uv_cpu_info_t* ci);
|
static int read_models(unsigned int numcpus, uv_cpu_info_t* ci);
|
||||||
static int read_times(unsigned int numcpus, uv_cpu_info_t* ci);
|
static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci);
|
||||||
static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
|
static void read_speeds(unsigned int numcpus, uv_cpu_info_t* ci);
|
||||||
static unsigned long read_cpufreq(unsigned int cpunum);
|
static unsigned long read_cpufreq(unsigned int cpunum);
|
||||||
|
|
||||||
@ -552,15 +552,48 @@ int uv_uptime(double* uptime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int uv__cpu_num(FILE* statfile_fp, unsigned int* numcpus) {
|
||||||
|
unsigned int num;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
if (!fgets(buf, sizeof(buf), statfile_fp))
|
||||||
|
abort();
|
||||||
|
|
||||||
|
num = 0;
|
||||||
|
while (fgets(buf, sizeof(buf), statfile_fp)) {
|
||||||
|
if (strncmp(buf, "cpu", 3))
|
||||||
|
break;
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
*numcpus = num;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
||||||
unsigned int numcpus;
|
unsigned int numcpus;
|
||||||
uv_cpu_info_t* ci;
|
uv_cpu_info_t* ci;
|
||||||
int err;
|
int err;
|
||||||
|
int statfile_fd;
|
||||||
|
FILE* statfile_fp;
|
||||||
|
|
||||||
*cpu_infos = NULL;
|
*cpu_infos = NULL;
|
||||||
*count = 0;
|
*count = 0;
|
||||||
|
|
||||||
numcpus = sysconf(_SC_NPROCESSORS_ONLN);
|
err = uv__open_cloexec("/proc/stat", O_RDONLY);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
statfile_fd = err;
|
||||||
|
|
||||||
|
statfile_fp = fdopen(statfile_fd, "r");
|
||||||
|
if (statfile_fp == NULL)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
err = uv__cpu_num(statfile_fp, &numcpus);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
assert(numcpus != (unsigned int) -1);
|
assert(numcpus != (unsigned int) -1);
|
||||||
assert(numcpus != 0);
|
assert(numcpus != 0);
|
||||||
|
|
||||||
@ -570,7 +603,10 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
|
|||||||
|
|
||||||
err = read_models(numcpus, ci);
|
err = read_models(numcpus, ci);
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
err = read_times(numcpus, ci);
|
rewind(statfile_fp);
|
||||||
|
err = read_times(statfile_fp, numcpus, ci);
|
||||||
|
|
||||||
|
uv__close(statfile_fd);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
uv_free_cpu_info(ci, numcpus);
|
uv_free_cpu_info(ci, numcpus);
|
||||||
@ -696,7 +732,7 @@ static int read_models(unsigned int numcpus, uv_cpu_info_t* ci) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
|
static int read_times(FILE* statfile_fp, unsigned int numcpus, uv_cpu_info_t* ci) {
|
||||||
unsigned long clock_ticks;
|
unsigned long clock_ticks;
|
||||||
struct uv_cpu_times_s ts;
|
struct uv_cpu_times_s ts;
|
||||||
unsigned long user;
|
unsigned long user;
|
||||||
@ -708,22 +744,19 @@ static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
|
|||||||
unsigned int num;
|
unsigned int num;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
FILE* fp;
|
|
||||||
|
|
||||||
clock_ticks = sysconf(_SC_CLK_TCK);
|
clock_ticks = sysconf(_SC_CLK_TCK);
|
||||||
assert(clock_ticks != (unsigned long) -1);
|
assert(clock_ticks != (unsigned long) -1);
|
||||||
assert(clock_ticks != 0);
|
assert(clock_ticks != 0);
|
||||||
|
|
||||||
fp = fopen("/proc/stat", "r");
|
rewind(statfile_fp);
|
||||||
if (fp == NULL)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
if (!fgets(buf, sizeof(buf), fp))
|
if (!fgets(buf, sizeof(buf), statfile_fp))
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
num = 0;
|
num = 0;
|
||||||
|
|
||||||
while (fgets(buf, sizeof(buf), fp)) {
|
while (fgets(buf, sizeof(buf), statfile_fp)) {
|
||||||
if (num >= numcpus)
|
if (num >= numcpus)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -762,7 +795,6 @@ static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
|
|||||||
ts.irq = clock_ticks * irq;
|
ts.irq = clock_ticks * irq;
|
||||||
ci[num++].cpu_times = ts;
|
ci[num++].cpu_times = ts;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
|
||||||
assert(num == numcpus);
|
assert(num == numcpus);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user