1
0
Fork 0
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:
Divy Srivastava 2022-11-02 00:17:00 -07:00 committed by GitHub
parent 5e4e324ceb
commit ab7e80bde4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 334 additions and 47 deletions

21
Cargo.lock generated
View file

@ -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"

View file

@ -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
View 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> | - |

View file

@ -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
View 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)
}