mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Prefer handling Duration
over f32
when dealing with times.
Also refactored out usage of the `time` crate in `uucore`.
This commit is contained in:
parent
63c17e5b42
commit
99fda0b716
7 changed files with 25 additions and 30 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1256,7 +1256,6 @@ name = "uucore"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -61,19 +61,12 @@ specified by the sum of their values.", NAME, VERSION);
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn float_to_duration(dur_f: f64) -> Duration {
|
|
||||||
let seconds = dur_f as u64;
|
|
||||||
let nanos = ((dur_f - seconds as f64) * 1e9) as u32;
|
|
||||||
Duration::new(seconds, nanos)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn sleep(args: Vec<String>) {
|
fn sleep(args: Vec<String>) {
|
||||||
let sleep_time = args.iter().fold(0.0, |result, arg|
|
let sleep_dur = args.iter().fold(Duration::new(0, 0), |result, arg|
|
||||||
match uucore::parse_time::from_str(&arg[..]) {
|
match uucore::parse_time::from_str(&arg[..]) {
|
||||||
Ok(m) => m + result,
|
Ok(m) => m + result,
|
||||||
Err(f) => crash!(1, "{}", f),
|
Err(f) => crash!(1, "{}", f),
|
||||||
});
|
});
|
||||||
let sleep_dur = float_to_duration(sleep_time);
|
|
||||||
|
|
||||||
thread::sleep(sleep_dur);
|
thread::sleep(sleep_dur);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ extern crate uucore;
|
||||||
|
|
||||||
use std::io::{ErrorKind, Write};
|
use std::io::{ErrorKind, Write};
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
use std::time::Duration;
|
||||||
use uucore::process::ChildExt;
|
use uucore::process::ChildExt;
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
|
@ -69,7 +70,7 @@ Usage:
|
||||||
return ERR_EXIT_STATUS;
|
return ERR_EXIT_STATUS;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => 0f64
|
None => Duration::new(0, 0),
|
||||||
};
|
};
|
||||||
let signal = match matches.opt_str("signal") {
|
let signal = match matches.opt_str("signal") {
|
||||||
Some(sigstr) => match uucore::signals::signal_by_name_or_value(&sigstr) {
|
Some(sigstr) => match uucore::signals::signal_by_name_or_value(&sigstr) {
|
||||||
|
@ -94,7 +95,7 @@ Usage:
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timeout(cmdname: &str, args: &[String], duration: f64, signal: usize, kill_after: f64, foreground: bool, preserve_status: bool) -> i32 {
|
fn timeout(cmdname: &str, args: &[String], duration: Duration, signal: usize, kill_after: Duration, foreground: bool, preserve_status: bool) -> i32 {
|
||||||
if !foreground {
|
if !foreground {
|
||||||
unsafe { setpgid(0, 0) };
|
unsafe { setpgid(0, 0) };
|
||||||
}
|
}
|
||||||
|
@ -128,7 +129,7 @@ fn timeout(cmdname: &str, args: &[String], duration: f64, signal: usize, kill_af
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
if kill_after == 0f64 {
|
if kill_after == Duration::new(0, 0) {
|
||||||
// XXX: this may not be right
|
// XXX: this may not be right
|
||||||
return 124;
|
return 124;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ authors = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "*"
|
libc = "*"
|
||||||
time = "*"
|
|
||||||
winapi = "*"
|
winapi = "*"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate time;
|
|
||||||
#[cfg(windows)] extern crate winapi;
|
#[cfg(windows)] extern crate winapi;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub fn from_str(string: &str) -> Result<f64, String> {
|
use std::time::Duration;
|
||||||
|
|
||||||
|
pub fn from_str(string: &str) -> Result<Duration, String> {
|
||||||
let len = string.len();
|
let len = string.len();
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
return Err("empty string".to_owned())
|
return Err("empty string".to_owned())
|
||||||
|
@ -28,8 +30,14 @@ pub fn from_str(string: &str) -> Result<f64, String> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match numstr.parse::<f64>() {
|
let num = match numstr.parse::<f64>() {
|
||||||
Ok(m) => Ok(m * times as f64),
|
Ok(m) => m,
|
||||||
Err(e) => Err(format!("invalid time interval '{}': {}", string, e))
|
Err(e) => return Err(format!("invalid time interval '{}': {}", string, e))
|
||||||
}
|
};
|
||||||
|
|
||||||
|
const NANOS_PER_SEC: u32 = 1_000_000_000;
|
||||||
|
let whole_secs = num.trunc();
|
||||||
|
let nanos = (num.fract() * (NANOS_PER_SEC as f64)).trunc();
|
||||||
|
let duration = Duration::new(whole_secs as u64, nanos as u32);
|
||||||
|
Ok(duration * times)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,7 @@ use std::io;
|
||||||
use std::process::Child;
|
use std::process::Child;
|
||||||
use std::sync::{Arc, Condvar, Mutex};
|
use std::sync::{Arc, Condvar, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use time::{Duration, get_time};
|
use std::time::{Duration, Instant};
|
||||||
use std::time::Duration as StdDuration;
|
|
||||||
|
|
||||||
// This is basically sys::unix::process::ExitStatus
|
// This is basically sys::unix::process::ExitStatus
|
||||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
|
@ -71,7 +70,7 @@ pub trait ChildExt {
|
||||||
fn send_signal(&mut self, signal: usize) -> io::Result<()>;
|
fn send_signal(&mut self, signal: usize) -> io::Result<()>;
|
||||||
|
|
||||||
/// Wait for a process to finish or return after the specified duration.
|
/// Wait for a process to finish or return after the specified duration.
|
||||||
fn wait_or_timeout(&mut self, timeout: f64) -> io::Result<Option<ExitStatus>>;
|
fn wait_or_timeout(&mut self, timeout: Duration) -> io::Result<Option<ExitStatus>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChildExt for Child {
|
impl ChildExt for Child {
|
||||||
|
@ -84,7 +83,7 @@ impl ChildExt for Child {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_or_timeout(&mut self, timeout: f64) -> io::Result<Option<ExitStatus>> {
|
fn wait_or_timeout(&mut self, timeout: Duration) -> io::Result<Option<ExitStatus>> {
|
||||||
// The result will be written to that Option, protected by a Mutex
|
// The result will be written to that Option, protected by a Mutex
|
||||||
// Then the Condvar will be signaled
|
// Then the Condvar will be signaled
|
||||||
let state = Arc::new((
|
let state = Arc::new((
|
||||||
|
@ -116,16 +115,13 @@ impl ChildExt for Child {
|
||||||
let &(ref lock, ref cvar) = &*state;
|
let &(ref lock, ref cvar) = &*state;
|
||||||
let mut exitstatus = lock.lock().unwrap();
|
let mut exitstatus = lock.lock().unwrap();
|
||||||
// Condvar::wait_timeout_ms() can wake too soon, in this case wait again
|
// Condvar::wait_timeout_ms() can wake too soon, in this case wait again
|
||||||
let target = get_time() +
|
let start = Instant::now();
|
||||||
Duration::seconds(timeout as i64) +
|
|
||||||
Duration::nanoseconds((timeout * 1.0e-6) as i64);
|
|
||||||
while exitstatus.is_none() {
|
while exitstatus.is_none() {
|
||||||
let now = get_time();
|
if start.elapsed() >= timeout {
|
||||||
if now >= target {
|
|
||||||
return Ok(None)
|
return Ok(None)
|
||||||
}
|
}
|
||||||
let ms = (target - get_time()).num_milliseconds() as u32;
|
let cvar_timeout = timeout - start.elapsed();
|
||||||
exitstatus = cvar.wait_timeout(exitstatus, StdDuration::new(0, ms*1000)).unwrap().0;
|
exitstatus = cvar.wait_timeout(exitstatus, cvar_timeout).unwrap().0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn Option<Result<ExitStatus>> into Result<Option<ExitStatus>>
|
// Turn Option<Result<ExitStatus>> into Result<Option<ExitStatus>>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue