Skip to content

Commit 0c812db

Browse files
committed
Fix a panic collecting cpu data on OSX
There's very little documentation on `host_processor_info` from what I can tell, so I'm just cribbing examples I've found elsewhere on the internet. It appears that I've misinterpreted one of the out parameters of `host_processor_info` as the number of elements of an array, but it actually is just something forwarded to `vm_deallocate`.
1 parent e8a9d3a commit 0c812db

File tree

1 file changed

+20
-14
lines changed

1 file changed

+20
-14
lines changed

src/cargo/util/cpu.rs

+20-14
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ mod imp {
9090
mod imp {
9191
use std::io;
9292
use std::ptr;
93-
use std::slice;
9493

9594
type host_t = u32;
9695
type mach_port_t = u32;
@@ -109,6 +108,7 @@ mod imp {
109108
const CPU_STATE_SYSTEM: usize = 1;
110109
const CPU_STATE_IDLE: usize = 2;
111110
const CPU_STATE_NICE: usize = 3;
111+
const CPU_STATE_MAX: usize = 4;
112112

113113
extern "C" {
114114
static mut mach_task_self_: mach_port_t;
@@ -135,39 +135,45 @@ mod imp {
135135
nice: u64,
136136
}
137137

138+
#[repr(C)]
139+
struct processor_cpu_load_info_data_t {
140+
cpu_ticks: [u32; CPU_STATE_MAX],
141+
}
142+
138143
pub fn current() -> io::Result<State> {
144+
// There's scant little documentation on `host_processor_info`
145+
// throughout the internet, so this is just modeled after what everyone
146+
// else is doing. For now this is modeled largely after libuv.
147+
139148
unsafe {
140149
let mut num_cpus_u = 0;
141150
let mut cpu_info = ptr::null_mut();
142-
let mut cpu_info_cnt = 0;
151+
let mut msg_type = 0;
143152
let err = host_processor_info(
144153
mach_host_self(),
145154
PROESSOR_CPU_LOAD_INFO,
146155
&mut num_cpus_u,
147156
&mut cpu_info,
148-
&mut cpu_info_cnt,
157+
&mut msg_type,
149158
);
150159
if err != 0 {
151160
return Err(io::Error::last_os_error());
152161
}
153-
let cpu_info_slice = slice::from_raw_parts(cpu_info, cpu_info_cnt as usize);
154162
let mut ret = State {
155163
user: 0,
156164
system: 0,
157165
idle: 0,
158166
nice: 0,
159167
};
160-
for chunk in cpu_info_slice.chunks(num_cpus_u as usize) {
161-
ret.user += chunk[CPU_STATE_USER] as u64;
162-
ret.system += chunk[CPU_STATE_SYSTEM] as u64;
163-
ret.idle += chunk[CPU_STATE_IDLE] as u64;
164-
ret.nice += chunk[CPU_STATE_NICE] as u64;
168+
let mut current = cpu_info as *const processor_cpu_load_info_data_t;
169+
for _ in 0..num_cpus_u {
170+
ret.user += (*current).cpu_ticks[CPU_STATE_USER] as u64;
171+
ret.system += (*current).cpu_ticks[CPU_STATE_SYSTEM] as u64;
172+
ret.idle += (*current).cpu_ticks[CPU_STATE_IDLE] as u64;
173+
ret.nice += (*current).cpu_ticks[CPU_STATE_NICE] as u64;
174+
current = current.offset(1);
165175
}
166-
vm_deallocate(
167-
mach_task_self_,
168-
cpu_info as vm_address_t,
169-
cpu_info_cnt as usize,
170-
);
176+
vm_deallocate(mach_task_self_, cpu_info as vm_address_t, msg_type as usize);
171177
Ok(ret)
172178
}
173179
}

0 commit comments

Comments
 (0)