mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
chore(runtime): remove dependency on sys-info crate (#16441)
Fixes #9862 `loadavg` | Target family | Syscall | Description | | ------------- | ------- | ----------- | | Linux | `sysinfo` | - | | Windows | - | Returns `DEFAULT_LOADAVG`. There is no concept of loadavg on Windows | | macOS, BSD | `getloadavg` | https://www.freebsd.org/cgi/man.cgi?query=getloadavg | `os_release` | Target family | Syscall | Description | | ------------- | ------- | ----------- | | Linux | `/proc/sys/kernel/osrelease` | - | | Windows | [`RtlGetVersion`](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlgetversion) | dwMajorVersion . dwMinorVersion . dwBuildNumber | | macOS | `sysctl([CTL_KERN, KERN_OSRELEASE])` | - | `hostname` | Target family | Syscall | Description | | ------------- | ------- | ----------- | | Unix | `gethostname(sysconf(_SC_HOST_NAME_MAX))` | - | | Windows | `GetHostNameW` | - | `mem_info` | Target family | Syscall | Description | | ------------- | ------- | ----------- | | Linux | sysinfo | - | | Windows | `sysinfoapi::GlobalMemoryStatusEx` | - | | macOS | <br> <pre> sysctl([CTL_HW, HW_MEMSIZE]); <br> sysctl([CTL_VM, VM_SWAPUSAGE]); <br> host_statistics64(mach_host_self(), HOST_VM_INFO64) </pre> | - |
This commit is contained in:
parent
5e4e324ceb
commit
ab7e80bde4
5 changed files with 334 additions and 47 deletions
21
Cargo.lock
generated
21
Cargo.lock
generated
|
@ -1211,12 +1211,12 @@ dependencies = [
|
|||
"netif",
|
||||
"nix",
|
||||
"notify",
|
||||
"ntapi",
|
||||
"once_cell",
|
||||
"regex",
|
||||
"ring",
|
||||
"serde",
|
||||
"signal-hook-registry",
|
||||
"sys-info",
|
||||
"termcolor",
|
||||
"test_util",
|
||||
"tokio",
|
||||
|
@ -2909,6 +2909,15 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc"
|
||||
dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.3"
|
||||
|
@ -4657,16 +4666,6 @@ dependencies = [
|
|||
"unicode-xid 0.2.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sys-info"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.38"
|
||||
|
|
|
@ -86,7 +86,6 @@ regex = "1.6.0"
|
|||
ring = "0.16.20"
|
||||
serde = { version = "1.0.136", features = ["derive"] }
|
||||
signal-hook-registry = "1.4.0"
|
||||
sys-info = "0.9.1"
|
||||
termcolor = "1.1.3"
|
||||
tokio = { version = "1.21", features = ["full"] }
|
||||
uuid = { version = "1.0.0", features = ["v4"] }
|
||||
|
@ -94,6 +93,7 @@ uuid = { version = "1.0.0", features = ["v4"] }
|
|||
[target.'cfg(windows)'.dependencies]
|
||||
fwdansi = "1.1.0"
|
||||
winapi = { version = "0.3.9", features = ["commapi", "knownfolders", "mswsock", "objbase", "shlobj", "tlhelp32", "winbase", "winerror", "winsock2"] }
|
||||
ntapi = "0.4.0"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
nix = "=0.24.2"
|
||||
|
|
32
runtime/ops/os/README.md
Normal file
32
runtime/ops/os/README.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
## `os` ops
|
||||
|
||||
`loadavg`
|
||||
|
||||
| Target family | Syscall | Description |
|
||||
| ------------- | ------------ | -------------------------------------------------------------------- |
|
||||
| Linux | `sysinfo` | - |
|
||||
| Windows | - | Returns `DEFAULT_LOADAVG`. There is no concept of loadavg on Windows |
|
||||
| macOS, BSD | `getloadavg` | https://www.freebsd.org/cgi/man.cgi?query=getloadavg |
|
||||
|
||||
`os_release`
|
||||
|
||||
| Target family | Syscall | Description |
|
||||
| ------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
|
||||
| Linux | `/proc/sys/kernel/osrelease` | - |
|
||||
| Windows | [`RtlGetVersion`](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-rtlgetversion) | dwMajorVersion . dwMinorVersion . dwBuildNumber |
|
||||
| macOS | `sysctl([CTL_KERN, KERN_OSRELEASE])` | - |
|
||||
|
||||
`hostname`
|
||||
|
||||
| Target family | Syscall | Description |
|
||||
| ------------- | ----------------------------------------- | ----------- |
|
||||
| Unix | `gethostname(sysconf(_SC_HOST_NAME_MAX))` | - |
|
||||
| Windows | `GetHostNameW` | - |
|
||||
|
||||
`mem_info`
|
||||
|
||||
| Target family | Syscall | Description |
|
||||
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| Linux | sysinfo | - |
|
||||
| Windows | `sysinfoapi::GlobalMemoryStatusEx` | - |
|
||||
| macOS | <br> <pre> sysctl([CTL_HW, HW_MEMSIZE]); <br> sysctl([CTL_VM, VM_SWAPUSAGE]); <br> host_statistics64(mach_host_self(), HOST_VM_INFO64) </pre> | - |
|
|
@ -9,10 +9,11 @@ use deno_core::Extension;
|
|||
use deno_core::OpState;
|
||||
use deno_core::{op, ExtensionBuilder};
|
||||
use deno_node::NODE_ENV_VAR_ALLOWLIST;
|
||||
use serde::Serialize;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
|
||||
mod sys_info;
|
||||
|
||||
fn init_ops(builder: &mut ExtensionBuilder) -> &mut ExtensionBuilder {
|
||||
builder.ops(vec![
|
||||
op_env::decl(),
|
||||
|
@ -164,10 +165,7 @@ fn op_loadavg(state: &mut OpState) -> Result<(f64, f64, f64), AnyError> {
|
|||
.borrow_mut::<Permissions>()
|
||||
.sys
|
||||
.check("loadavg", Some("Deno.loadavg()"))?;
|
||||
match sys_info::loadavg() {
|
||||
Ok(loadavg) => Ok((loadavg.one, loadavg.five, loadavg.fifteen)),
|
||||
Err(_) => Ok((0.0, 0.0, 0.0)),
|
||||
}
|
||||
Ok(sys_info::loadavg())
|
||||
}
|
||||
|
||||
#[op]
|
||||
|
@ -176,8 +174,7 @@ fn op_hostname(state: &mut OpState) -> Result<String, AnyError> {
|
|||
.borrow_mut::<Permissions>()
|
||||
.sys
|
||||
.check("hostname", Some("Deno.hostname()"))?;
|
||||
let hostname = sys_info::hostname().unwrap_or_else(|_| "".to_string());
|
||||
Ok(hostname)
|
||||
Ok(sys_info::hostname())
|
||||
}
|
||||
|
||||
#[op]
|
||||
|
@ -186,8 +183,7 @@ fn op_os_release(state: &mut OpState) -> Result<String, AnyError> {
|
|||
.borrow_mut::<Permissions>()
|
||||
.sys
|
||||
.check("osRelease", Some("Deno.osRelease()"))?;
|
||||
let release = sys_info::os_release().unwrap_or_else(|_| "".to_string());
|
||||
Ok(release)
|
||||
Ok(sys_info::os_release())
|
||||
}
|
||||
|
||||
#[op]
|
||||
|
@ -246,40 +242,16 @@ impl From<netif::Interface> for NetworkInterface {
|
|||
}
|
||||
}
|
||||
|
||||
// Copied from sys-info/lib.rs (then tweaked)
|
||||
#[derive(Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct MemInfo {
|
||||
pub total: u64,
|
||||
pub free: u64,
|
||||
pub available: u64,
|
||||
pub buffers: u64,
|
||||
pub cached: u64,
|
||||
pub swap_total: u64,
|
||||
pub swap_free: u64,
|
||||
}
|
||||
|
||||
#[op]
|
||||
fn op_system_memory_info(
|
||||
state: &mut OpState,
|
||||
) -> Result<Option<MemInfo>, AnyError> {
|
||||
) -> Result<Option<sys_info::MemInfo>, AnyError> {
|
||||
super::check_unstable(state, "Deno.systemMemoryInfo");
|
||||
state
|
||||
.borrow_mut::<Permissions>()
|
||||
.sys
|
||||
.check("systemMemoryInfo", Some("Deno.systemMemoryInfo()"))?;
|
||||
match sys_info::mem_info() {
|
||||
Ok(info) => Ok(Some(MemInfo {
|
||||
total: info.total,
|
||||
free: info.free,
|
||||
available: info.avail,
|
||||
buffers: info.buffers,
|
||||
cached: info.cached,
|
||||
swap_total: info.swap_total,
|
||||
swap_free: info.swap_free,
|
||||
})),
|
||||
Err(_) => Ok(None),
|
||||
}
|
||||
Ok(sys_info::mem_info())
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
284
runtime/ops/os/sys_info.rs
Normal file
284
runtime/ops/os/sys_info.rs
Normal file
|
@ -0,0 +1,284 @@
|
|||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
type LoadAvg = (f64, f64, f64);
|
||||
const DEFAULT_LOADAVG: LoadAvg = (0.0, 0.0, 0.0);
|
||||
|
||||
pub fn loadavg() -> LoadAvg {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
use libc::SI_LOAD_SHIFT;
|
||||
|
||||
let mut info = std::mem::MaybeUninit::uninit();
|
||||
// SAFETY: `info` is a valid pointer to a `libc::sysinfo` struct.
|
||||
let res = unsafe { libc::sysinfo(info.as_mut_ptr()) };
|
||||
if res == 0 {
|
||||
// SAFETY: `sysinfo` returns 0 on success, and `info` is initialized.
|
||||
let info = unsafe { info.assume_init() };
|
||||
(
|
||||
info.loads[0] as f64 / (1 << SI_LOAD_SHIFT) as f64,
|
||||
info.loads[1] as f64 / (1 << SI_LOAD_SHIFT) as f64,
|
||||
info.loads[2] as f64 / (1 << SI_LOAD_SHIFT) as f64,
|
||||
)
|
||||
} else {
|
||||
DEFAULT_LOADAVG
|
||||
}
|
||||
}
|
||||
#[cfg(any(
|
||||
target_vendor = "apple",
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd"
|
||||
))]
|
||||
{
|
||||
let mut l: [f64; 3] = [0.; 3];
|
||||
// SAFETY: `&mut l` is a valid pointer to an array of 3 doubles
|
||||
if unsafe { libc::getloadavg(&mut l as *mut f64, l.len() as _) } < 3 {
|
||||
DEFAULT_LOADAVG
|
||||
} else {
|
||||
(l[0], l[1], l[2])
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
DEFAULT_LOADAVG
|
||||
}
|
||||
}
|
||||
|
||||
pub fn os_release() -> String {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
match std::fs::read_to_string("/proc/sys/kernel/osrelease") {
|
||||
Ok(mut s) => {
|
||||
s.pop(); // pop '\n'
|
||||
s
|
||||
}
|
||||
_ => String::from(""),
|
||||
}
|
||||
}
|
||||
#[cfg(target_vendor = "apple")]
|
||||
{
|
||||
let mut s = [0u8; 256];
|
||||
let mut mib = [libc::CTL_KERN, libc::KERN_OSRELEASE];
|
||||
// 256 is enough.
|
||||
let mut len = s.len();
|
||||
// SAFETY: `sysctl` is thread-safe.
|
||||
// `s` is only accessed if sysctl() succeeds and agrees with the `len` set
|
||||
// by sysctl().
|
||||
if unsafe {
|
||||
libc::sysctl(
|
||||
mib.as_mut_ptr(),
|
||||
mib.len() as _,
|
||||
s.as_mut_ptr() as _,
|
||||
&mut len,
|
||||
std::ptr::null_mut(),
|
||||
0,
|
||||
)
|
||||
} == -1
|
||||
{
|
||||
return String::from("Unknown");
|
||||
}
|
||||
|
||||
// without the NUL terminator
|
||||
return String::from_utf8_lossy(&s[..len - 1]).to_string();
|
||||
}
|
||||
#[cfg(target_family = "windows")]
|
||||
{
|
||||
use ntapi::ntrtl::RtlGetVersion;
|
||||
use winapi::shared::ntdef::NT_SUCCESS;
|
||||
use winapi::um::winnt::RTL_OSVERSIONINFOEXW;
|
||||
|
||||
let mut version_info =
|
||||
std::mem::MaybeUninit::<RTL_OSVERSIONINFOEXW>::uninit();
|
||||
// SAFETY: we need to initialize dwOSVersionInfoSize.
|
||||
unsafe {
|
||||
(*version_info.as_mut_ptr()).dwOSVersionInfoSize =
|
||||
std::mem::size_of::<RTL_OSVERSIONINFOEXW>() as u32;
|
||||
}
|
||||
// SAFETY: `version_info` is pointer to a valid `RTL_OSVERSIONINFOEXW` struct and
|
||||
// dwOSVersionInfoSize is set to the size of RTL_OSVERSIONINFOEXW.
|
||||
if !NT_SUCCESS(unsafe {
|
||||
RtlGetVersion(version_info.as_mut_ptr() as *mut _)
|
||||
}) {
|
||||
String::from("")
|
||||
} else {
|
||||
// SAFETY: we assume that RtlGetVersion() initializes the fields.
|
||||
let version_info = unsafe { version_info.assume_init() };
|
||||
format!(
|
||||
"{}.{}.{}",
|
||||
version_info.dwMajorVersion,
|
||||
version_info.dwMinorVersion,
|
||||
version_info.dwBuildNumber
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hostname() -> String {
|
||||
#[cfg(target_family = "unix")]
|
||||
// SAFETY: `sysconf` returns a system constant.
|
||||
unsafe {
|
||||
let buf_size = libc::sysconf(libc::_SC_HOST_NAME_MAX) as usize;
|
||||
let mut buf = vec![0u8; buf_size + 1];
|
||||
let len = buf.len();
|
||||
if libc::gethostname(buf.as_mut_ptr() as *mut libc::c_char, len) < 0 {
|
||||
return String::from("");
|
||||
}
|
||||
// ensure NUL termination
|
||||
buf[len - 1] = 0;
|
||||
std::ffi::CStr::from_ptr(buf.as_ptr() as *const libc::c_char)
|
||||
.to_string_lossy()
|
||||
.to_string()
|
||||
}
|
||||
#[cfg(target_family = "windows")]
|
||||
{
|
||||
use std::ffi::OsString;
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
use winapi::um::winsock2::GetHostNameW;
|
||||
|
||||
let namelen = 256;
|
||||
let mut name: Vec<u16> = vec![0u16; namelen];
|
||||
let err =
|
||||
// SAFETY: length of wide string is 256 chars or less.
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-gethostnamew
|
||||
unsafe { GetHostNameW(name.as_mut_ptr(), namelen as libc::c_int) };
|
||||
|
||||
if err == 0 {
|
||||
// TODO(@littledivy): Probably not the most efficient way.
|
||||
let len = name.iter().take_while(|&&c| c != 0).count();
|
||||
OsString::from_wide(&name[..len])
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
} else {
|
||||
String::from("")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MemInfo {
|
||||
pub total: u64,
|
||||
pub free: u64,
|
||||
pub available: u64,
|
||||
pub buffers: u64,
|
||||
pub cached: u64,
|
||||
pub swap_total: u64,
|
||||
pub swap_free: u64,
|
||||
}
|
||||
|
||||
pub fn mem_info() -> Option<MemInfo> {
|
||||
let mut mem_info = MemInfo {
|
||||
total: 0,
|
||||
free: 0,
|
||||
available: 0,
|
||||
buffers: 0,
|
||||
cached: 0,
|
||||
swap_total: 0,
|
||||
swap_free: 0,
|
||||
};
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let mut info = std::mem::MaybeUninit::uninit();
|
||||
// SAFETY: `info` is a valid pointer to a `libc::sysinfo` struct.
|
||||
let res = unsafe { libc::sysinfo(info.as_mut_ptr()) };
|
||||
if res == 0 {
|
||||
// SAFETY: `sysinfo` initializes the struct.
|
||||
let info = unsafe { info.assume_init() };
|
||||
let mem_unit = info.mem_unit as u64;
|
||||
mem_info.swap_total = info.totalswap * mem_unit;
|
||||
mem_info.swap_free = info.freeswap * mem_unit;
|
||||
mem_info.total = info.totalram * mem_unit;
|
||||
mem_info.free = info.freeram * mem_unit;
|
||||
mem_info.buffers = info.bufferram * mem_unit;
|
||||
}
|
||||
}
|
||||
#[cfg(any(target_vendor = "apple"))]
|
||||
{
|
||||
let mut mib: [i32; 2] = [0, 0];
|
||||
mib[0] = libc::CTL_HW;
|
||||
mib[1] = libc::HW_MEMSIZE;
|
||||
// SAFETY:
|
||||
// - We assume that `mach_host_self` always returns a valid value.
|
||||
// - sysconf returns a system constant.
|
||||
unsafe {
|
||||
let mut size = std::mem::size_of::<u64>();
|
||||
libc::sysctl(
|
||||
mib.as_mut_ptr(),
|
||||
mib.len() as _,
|
||||
&mut mem_info.total as *mut _ as *mut libc::c_void,
|
||||
&mut size,
|
||||
std::ptr::null_mut(),
|
||||
0,
|
||||
);
|
||||
mem_info.total /= 1024;
|
||||
|
||||
let mut xs: libc::xsw_usage = std::mem::zeroed::<libc::xsw_usage>();
|
||||
mib[0] = libc::CTL_VM;
|
||||
mib[1] = libc::VM_SWAPUSAGE;
|
||||
|
||||
let mut size = std::mem::size_of::<libc::xsw_usage>();
|
||||
libc::sysctl(
|
||||
mib.as_mut_ptr(),
|
||||
mib.len() as _,
|
||||
&mut xs as *mut _ as *mut libc::c_void,
|
||||
&mut size,
|
||||
std::ptr::null_mut(),
|
||||
0,
|
||||
);
|
||||
|
||||
mem_info.swap_total = xs.xsu_total;
|
||||
mem_info.swap_free = xs.xsu_avail;
|
||||
|
||||
let mut count: u32 = libc::HOST_VM_INFO64_COUNT as _;
|
||||
let mut stat = unsafe { std::mem::zeroed::<libc::vm_statistics64>() };
|
||||
if libc::host_statistics64(
|
||||
// TODO(@littledivy): Put this in a once_cell.
|
||||
libc::mach_host_self(),
|
||||
libc::HOST_VM_INFO64,
|
||||
&mut stat as *mut libc::vm_statistics64 as *mut _,
|
||||
&mut count,
|
||||
) == libc::KERN_SUCCESS
|
||||
{
|
||||
// TODO(@littledivy): Put this in a once_cell
|
||||
let page_size = libc::sysconf(libc::_SC_PAGESIZE) as u64;
|
||||
mem_info.available =
|
||||
(stat.free_count as u64 + stat.inactive_count as u64) * page_size
|
||||
/ 1024;
|
||||
mem_info.free =
|
||||
(stat.free_count as u64 - stat.speculative_count as u64) * page_size
|
||||
/ 1024;
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(target_family = "windows")]
|
||||
// SAFETY:
|
||||
// - `mem_status` is a valid pointer to a `libc::MEMORYSTATUSEX` struct.
|
||||
// - `dwLength` is set to the size of the struct.
|
||||
unsafe {
|
||||
use std::mem;
|
||||
use winapi::shared::minwindef;
|
||||
use winapi::um::sysinfoapi;
|
||||
|
||||
let mut mem_status =
|
||||
mem::MaybeUninit::<sysinfoapi::MEMORYSTATUSEX>::uninit();
|
||||
let length =
|
||||
mem::size_of::<sysinfoapi::MEMORYSTATUSEX>() as minwindef::DWORD;
|
||||
(*mem_status.as_mut_ptr()).dwLength = length;
|
||||
|
||||
let result = sysinfoapi::GlobalMemoryStatusEx(mem_status.as_mut_ptr());
|
||||
if result != 0 {
|
||||
let stat = mem_status.assume_init();
|
||||
mem_info.total = stat.ullTotalPhys / 1024;
|
||||
mem_info.available = 0;
|
||||
mem_info.free = stat.ullAvailPhys / 1024;
|
||||
mem_info.cached = 0;
|
||||
mem_info.buffers = 0;
|
||||
mem_info.swap_total = (stat.ullTotalPageFile - stat.ullTotalPhys) / 1024;
|
||||
mem_info.swap_free = (stat.ullAvailPageFile - stat.ullAvailPhys) / 1024;
|
||||
if mem_info.swap_free > mem_info.swap_total {
|
||||
mem_info.swap_free = mem_info.swap_total;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(mem_info)
|
||||
}
|
Loading…
Reference in a new issue