]> git.proxmox.com Git - proxmox-backup.git/commitdiff
remove timer and lock functions, fix building with proxmox 0.3.2
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Tue, 4 Aug 2020 09:33:02 +0000 (11:33 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Tue, 4 Aug 2020 09:33:02 +0000 (11:33 +0200)
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
src/api2/access/acl.rs
src/api2/access/user.rs
src/api2/config/datastore.rs
src/api2/config/remote.rs
src/api2/config/sync.rs
src/api2/node/network.rs
src/backup/backup_info.rs
src/server/worker_task.rs
src/tools.rs
src/tools/timer.rs [deleted file]

index 4fed4652eee2afcde91bd5d6bbd25cae840b7a91..7187538f6560d7e7595eac43e3b9a5ee50d4ca0f 100644 (file)
@@ -2,6 +2,7 @@ use anyhow::{bail, Error};
 use ::serde::{Deserialize, Serialize};
 
 use proxmox::api::{api, Router, RpcEnvironment, Permission};
+use proxmox::tools::fs::open_file_locked;
 
 use crate::api2::types::*;
 use crate::config::acl;
@@ -174,7 +175,7 @@ pub fn update_acl(
     _rpcenv: &mut dyn RpcEnvironment,
 ) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(acl::ACL_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(acl::ACL_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let (mut tree, expected_digest) = acl::config()?;
 
index 2d6b35e7ef548d0dfd8745e323fbe1f20070d11f..b3f70dcf54c7f9365e12dcaaa79ea9ecf8f3c114 100644 (file)
@@ -3,6 +3,7 @@ use serde_json::Value;
 
 use proxmox::api::{api, ApiMethod, Router, RpcEnvironment, Permission};
 use proxmox::api::schema::{Schema, StringSchema};
+use proxmox::tools::fs::open_file_locked;
 
 use crate::api2::types::*;
 use crate::config::user;
@@ -87,7 +88,7 @@ pub fn list_users(
 /// Create new user.
 pub fn create_user(password: Option<String>, param: Value) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(user::USER_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(user::USER_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let user: user::User = serde_json::from_value(param)?;
 
@@ -193,7 +194,7 @@ pub fn update_user(
     digest: Option<String>,
 ) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(user::USER_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(user::USER_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let (mut config, expected_digest) = user::config()?;
 
@@ -265,7 +266,7 @@ pub fn update_user(
 /// Remove a user from the configuration file.
 pub fn delete_user(userid: String, digest: Option<String>) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(user::USER_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(user::USER_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let (mut config, expected_digest) = user::config()?;
 
index 7bb13c4b70e2c687417e13224867dd9c30ad223a..1ee303f80fc58b952e85d1152c82904f69b4f21a 100644 (file)
@@ -5,6 +5,7 @@ use serde_json::Value;
 use ::serde::{Deserialize, Serialize};
 
 use proxmox::api::{api, Router, RpcEnvironment, Permission};
+use proxmox::tools::fs::open_file_locked;
 
 use crate::api2::types::*;
 use crate::backup::*;
@@ -99,7 +100,7 @@ pub fn list_datastores(
 /// Create new datastore config.
 pub fn create_datastore(param: Value) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(datastore::DATASTORE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(datastore::DATASTORE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let datastore: datastore::DataStoreConfig = serde_json::from_value(param.clone())?;
 
@@ -253,7 +254,7 @@ pub fn update_datastore(
     digest: Option<String>,
 ) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(datastore::DATASTORE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(datastore::DATASTORE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     // pass/compare digest
     let (mut config, expected_digest) = datastore::config()?;
@@ -327,7 +328,7 @@ pub fn update_datastore(
 /// Remove a datastore configuration.
 pub fn delete_datastore(name: String, digest: Option<String>) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(datastore::DATASTORE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(datastore::DATASTORE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let (mut config, expected_digest) = datastore::config()?;
 
index 187515b829a308845f0d8ef22af05532bfaaabf6..237e7b14a4dbb446998ce2df1b5c6abbbbdeab56 100644 (file)
@@ -4,6 +4,7 @@ use ::serde::{Deserialize, Serialize};
 use base64;
 
 use proxmox::api::{api, ApiMethod, Router, RpcEnvironment, Permission};
+use proxmox::tools::fs::open_file_locked;
 
 use crate::api2::types::*;
 use crate::config::remote;
@@ -78,7 +79,7 @@ pub fn list_remotes(
 /// Create new remote.
 pub fn create_remote(password: String, param: Value) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(remote::REMOTE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(remote::REMOTE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let mut data = param.clone();
     data["password"] = Value::from(base64::encode(password.as_bytes()));
@@ -194,7 +195,7 @@ pub fn update_remote(
     digest: Option<String>,
 ) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(remote::REMOTE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(remote::REMOTE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let (mut config, expected_digest) = remote::config()?;
 
@@ -255,7 +256,7 @@ pub fn update_remote(
 /// Remove a remote from the configuration file.
 pub fn delete_remote(name: String, digest: Option<String>) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(remote::REMOTE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(remote::REMOTE_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let (mut config, expected_digest) = remote::config()?;
 
index 860dcc36ff9ddfa50e8f53c9bbdbcd00c7bd8f4b..8273a4b4a8c238e03f617bc1b23331a39ba784b2 100644 (file)
@@ -3,6 +3,7 @@ use serde_json::Value;
 use ::serde::{Deserialize, Serialize};
 
 use proxmox::api::{api, Router, RpcEnvironment};
+use proxmox::tools::fs::open_file_locked;
 
 use crate::api2::types::*;
 use crate::config::sync::{self, SyncJobConfig};
@@ -68,7 +69,7 @@ pub fn list_sync_jobs(
 /// Create a new sync job.
 pub fn create_sync_job(param: Value) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(sync::SYNC_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(sync::SYNC_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let sync_job: sync::SyncJobConfig = serde_json::from_value(param.clone())?;
 
@@ -184,7 +185,7 @@ pub fn update_sync_job(
     digest: Option<String>,
 ) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(sync::SYNC_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(sync::SYNC_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     // pass/compare digest
     let (mut config, expected_digest) = sync::config()?;
@@ -247,7 +248,7 @@ pub fn update_sync_job(
 /// Remove a sync job configuration
 pub fn delete_sync_job(id: String, digest: Option<String>) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(sync::SYNC_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(sync::SYNC_CFG_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let (mut config, expected_digest) = sync::config()?;
 
index c0c55333481f4eb1581a8f1bc6783ce78d390f57..69ce0df65a79959d40e41242aca28a7c10e41a3d 100644 (file)
@@ -4,6 +4,7 @@ use ::serde::{Deserialize, Serialize};
 
 use proxmox::api::{api, ApiMethod, Router, RpcEnvironment, Permission};
 use proxmox::api::schema::parse_property_string;
+use proxmox::tools::fs::open_file_locked;
 
 use crate::config::network::{self, NetworkConfig};
 use crate::config::acl::{PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
@@ -230,7 +231,7 @@ pub fn create_interface(
     let interface_type = crate::tools::required_string_param(&param, "type")?;
     let interface_type: NetworkInterfaceType = serde_json::from_value(interface_type.into())?;
 
-    let _lock = crate::tools::open_file_locked(network::NETWORK_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(network::NETWORK_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let (mut config, _digest) = network::config()?;
 
@@ -463,7 +464,7 @@ pub fn update_interface(
     param: Value,
 ) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(network::NETWORK_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(network::NETWORK_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let (mut config, expected_digest) = network::config()?;
 
@@ -586,7 +587,7 @@ pub fn update_interface(
 /// Remove network interface configuration.
 pub fn delete_interface(iface: String, digest: Option<String>) -> Result<(), Error> {
 
-    let _lock = crate::tools::open_file_locked(network::NETWORK_LOCKFILE, std::time::Duration::new(10, 0))?;
+    let _lock = open_file_locked(network::NETWORK_LOCKFILE, std::time::Duration::new(10, 0))?;
 
     let (mut config, expected_digest) = network::config()?;
 
index ba5ea1a30ca93dd129f8caa8cc1b9b30d6b130eb..37dc7aa176940dc56a7582911b56688a95f916c7 100644 (file)
@@ -155,7 +155,7 @@ impl BackupGroup {
 
         // acquire in non-blocking mode, no point in waiting here since other
         // backups could still take a very long time
-        tools::lock_file(&mut handle, true, Some(Duration::from_nanos(0)))
+        proxmox::tools::fs::lock_file(&mut handle, true, Some(Duration::from_nanos(0)))
             .map_err(|err| {
                 format_err!(
                     "unable to acquire lock on backup group {:?} - {}",
index fdbbacbe616f02c915e33ed0952f201fbb733346..f0e284882f5909b72252b900af6358deea6e8484 100644 (file)
@@ -15,7 +15,7 @@ use tokio::sync::oneshot;
 
 use proxmox::sys::linux::procfs;
 use proxmox::try_block;
-use proxmox::tools::fs::{create_path, replace_file, CreateOptions};
+use proxmox::tools::fs::{create_path, open_file_locked, replace_file, CreateOptions};
 
 use super::UPID;
 
@@ -247,7 +247,7 @@ fn update_active_workers(new_upid: Option<&UPID>) -> Result<Vec<TaskListInfo>, E
 
     let backup_user = crate::backup::backup_user()?;
 
-    let lock = crate::tools::open_file_locked(PROXMOX_BACKUP_TASK_LOCK_FN, std::time::Duration::new(10, 0))?;
+    let lock = open_file_locked(PROXMOX_BACKUP_TASK_LOCK_FN, std::time::Duration::new(10, 0))?;
     nix::unistd::chown(PROXMOX_BACKUP_TASK_LOCK_FN, Some(backup_user.uid), Some(backup_user.gid))?;
 
     let reader = match File::open(PROXMOX_BACKUP_ACTIVE_TASK_FN) {
index c1045c16222c0ad10d0201fba9f0b316f9e6f416..8792bf0c4fa3ad1501292c91106e169a6985ca86 100644 (file)
@@ -4,9 +4,9 @@
 use std::any::Any;
 use std::collections::HashMap;
 use std::hash::BuildHasher;
-use std::fs::{File, OpenOptions};
+use std::fs::File;
 use std::io::{self, BufRead, ErrorKind, Read};
-use std::os::unix::io::{AsRawFd, RawFd};
+use std::os::unix::io::RawFd;
 use std::path::Path;
 use std::time::Duration;
 use std::time::{SystemTime, SystemTimeError, UNIX_EPOCH};
@@ -17,7 +17,6 @@ use openssl::hash::{hash, DigestBytes, MessageDigest};
 use percent_encoding::AsciiSet;
 
 use proxmox::tools::vec;
-use proxmox::sys::error::SysResult;
 
 pub use proxmox::tools::fd::Fd;
 
@@ -32,7 +31,6 @@ pub mod format;
 pub mod lru_cache;
 pub mod runtime;
 pub mod ticket;
-pub mod timer;
 pub mod statistics;
 pub mod systemd;
 pub mod nom;
@@ -90,73 +88,6 @@ pub fn map_struct_mut<T>(buffer: &mut [u8]) -> Result<&mut T, Error> {
     Ok(unsafe { &mut *(buffer.as_ptr() as *mut T) })
 }
 
-/// Create a file lock using fntl. This function allows you to specify
-/// a timeout if you want to avoid infinite blocking.
-///
-/// With timeout set to 0, non-blocking mode is used and the function
-/// will fail immediately if the lock can't be acquired.
-pub fn lock_file<F: AsRawFd>(
-    file: &mut F,
-    exclusive: bool,
-    timeout: Option<Duration>,
-) -> Result<(), io::Error> {
-    let lockarg = if exclusive {
-        nix::fcntl::FlockArg::LockExclusive
-    } else {
-        nix::fcntl::FlockArg::LockShared
-    };
-
-    let timeout = match timeout {
-        None => {
-            nix::fcntl::flock(file.as_raw_fd(), lockarg).into_io_result()?;
-            return Ok(());
-        }
-        Some(t) => t,
-    };
-
-    if timeout.as_nanos() == 0 {
-        let lockarg = if exclusive {
-            nix::fcntl::FlockArg::LockExclusiveNonblock
-        } else {
-            nix::fcntl::FlockArg::LockSharedNonblock
-        };
-        nix::fcntl::flock(file.as_raw_fd(), lockarg).into_io_result()?;
-        return Ok(());
-    }
-
-    // unblock the timeout signal temporarily
-    let _sigblock_guard = timer::unblock_timeout_signal();
-
-    // setup a timeout timer
-    let mut timer = timer::Timer::create(
-        timer::Clock::Realtime,
-        timer::TimerEvent::ThisThreadSignal(timer::SIGTIMEOUT),
-    )?;
-
-    timer.arm(
-        timer::TimerSpec::new()
-            .value(Some(timeout))
-            .interval(Some(Duration::from_millis(10))),
-    )?;
-
-    nix::fcntl::flock(file.as_raw_fd(), lockarg).into_io_result()?;
-    Ok(())
-}
-
-/// Open or create a lock file (append mode). Then try to
-/// acquire a lock using `lock_file()`.
-pub fn open_file_locked<P: AsRef<Path>>(path: P, timeout: Duration) -> Result<File, Error> {
-    let path = path.as_ref();
-    let mut file = match OpenOptions::new().create(true).append(true).open(path) {
-        Ok(file) => file,
-        Err(err) => bail!("Unable to open lock {:?} - {}", path, err),
-    };
-    match lock_file(&mut file, true, Some(timeout)) {
-        Ok(_) => Ok(file),
-        Err(err) => bail!("Unable to acquire lock {:?} - {}", path, err),
-    }
-}
-
 /// Split a file into equal sized chunks. The last chunk may be
 /// smaller. Note: We cannot implement an `Iterator`, because iterators
 /// cannot return a borrowed buffer ref (we want zero-copy)
diff --git a/src/tools/timer.rs b/src/tools/timer.rs
deleted file mode 100644 (file)
index 40877a1..0000000
+++ /dev/null
@@ -1,370 +0,0 @@
-//! POSIX per-process timer interface.
-//!
-//! This module provides a wrapper around POSIX timers (see `timer_create(2)`) and utilities to
-//! setup thread-targeted signaling and signal masks.
-
-use std::mem::MaybeUninit;
-use std::time::Duration;
-use std::{io, mem};
-
-use libc::{c_int, clockid_t, pid_t};
-
-/// Timers can use various clocks. See `timer_create(2)`.
-pub enum Clock {
-    /// Use `CLOCK_REALTIME` for the timer.
-    Realtime,
-    /// Use `CLOCK_MONOTONIC` for the timer.
-    Monotonic,
-}
-
-/// Strong thread-id type to prevent accidental conversion of pid_t.
-pub struct Tid(pid_t);
-
-/// Convenience helper to get the current thread ID suitable to pass to a
-/// `TimerEvent::ThreadSignal` entry.
-pub fn gettid() -> Tid {
-    Tid(unsafe { libc::syscall(libc::SYS_gettid) } as pid_t)
-}
-
-/// Strong signal type which is more advanced than nix::sys::signal::Signal as
-/// it doesn't prevent you from using signals that the nix crate is unaware
-/// of...!
-pub struct Signal(c_int);
-
-impl Into<c_int> for Signal {
-    fn into(self) -> c_int {
-        self.0
-    }
-}
-
-impl From<c_int> for Signal {
-    fn from(v: c_int) -> Signal {
-        Signal(v)
-    }
-}
-
-/// When instantiating a Timer, it needs to have an event type associated with
-/// it to be fired whenever the timer expires. Most of the time this will be a
-/// `Signal`. Sometimes we need to be able to send signals to specific threads.
-pub enum TimerEvent {
-    /// This will act like passing `NULL` to `timer_create()`, which maps to
-    /// using the same as `Signal(SIGALRM)`.
-    None,
-
-    /// When the timer expires, send a specific signal to the current process.
-    Signal(Signal),
-
-    /// When the timer expires, send a specific signal to a specific thread.
-    ThreadSignal(Tid, Signal),
-
-    /// Convenience value to send a signal to the current thread. This is
-    /// equivalent to using `ThreadSignal(gettid(), signal)`.
-    ThisThreadSignal(Signal),
-}
-
-// timer_t is a pointer type, so we create a strongly typed internal handle
-// type for it
-#[repr(C)]
-struct InternalTimerT(u32);
-type TimerT = *mut InternalTimerT;
-
-// These wrappers are defined in -lrt.
-#[link(name = "rt")]
-extern "C" {
-    fn timer_create(clockid: clockid_t, evp: *mut libc::sigevent, timer: *mut TimerT) -> c_int;
-    fn timer_delete(timer: TimerT) -> c_int;
-    fn timer_settime(
-        timerid: TimerT,
-        flags: c_int,
-        new_value: *const libc::itimerspec,
-        old_value: *mut libc::itimerspec,
-    ) -> c_int;
-}
-
-/// Represents a POSIX per-process timer as created via `timer_create(2)`.
-pub struct Timer {
-    timer: TimerT,
-}
-
-/// Timer specification used to arm a `Timer`.
-#[derive(Default)]
-pub struct TimerSpec {
-    /// The timeout to the next timer event.
-    pub value: Option<Duration>,
-
-    /// When a timer expires, it may be automatically rearmed with another
-    /// timeout. This will keep happening until this is explicitly disabled
-    /// or the timer deleted.
-    pub interval: Option<Duration>,
-}
-
-// Helpers to convert between libc::timespec and Option<Duration>
-fn opt_duration_to_timespec(v: Option<Duration>) -> libc::timespec {
-    match v {
-        None => libc::timespec {
-            tv_sec: 0,
-            tv_nsec: 0,
-        },
-        Some(value) => libc::timespec {
-            tv_sec: value.as_secs() as i64,
-            tv_nsec: value.subsec_nanos() as i64,
-        },
-    }
-}
-
-fn timespec_to_opt_duration(v: libc::timespec) -> Option<Duration> {
-    if v.tv_sec == 0 && v.tv_nsec == 0 {
-        None
-    } else {
-        Some(Duration::new(v.tv_sec as u64, v.tv_nsec as u32))
-    }
-}
-
-impl TimerSpec {
-    // Helpers to convert between TimerSpec and libc::itimerspec
-    fn to_itimerspec(&self) -> libc::itimerspec {
-        libc::itimerspec {
-            it_value: opt_duration_to_timespec(self.value),
-            it_interval: opt_duration_to_timespec(self.interval),
-        }
-    }
-
-    fn from_itimerspec(ts: libc::itimerspec) -> Self {
-        TimerSpec {
-            value: timespec_to_opt_duration(ts.it_value),
-            interval: timespec_to_opt_duration(ts.it_interval),
-        }
-    }
-
-    /// Create an empty timer specification representing a disabled timer.
-    pub fn new() -> Self {
-        TimerSpec {
-            value: None,
-            interval: None,
-        }
-    }
-
-    /// Change the specification to have a specific value.
-    pub fn value(self, value: Option<Duration>) -> Self {
-        TimerSpec {
-            value,
-            interval: self.interval,
-        }
-    }
-
-    /// Change the specification to have a specific interval.
-    pub fn interval(self, interval: Option<Duration>) -> Self {
-        TimerSpec {
-            value: self.value,
-            interval,
-        }
-    }
-}
-
-impl Timer {
-    /// Create a Timer object governing a POSIX timer.
-    pub fn create(clock: Clock, event: TimerEvent) -> io::Result<Timer> {
-        // Map from our clock type to the libc id
-        let clkid = match clock {
-            Clock::Realtime => libc::CLOCK_REALTIME,
-            Clock::Monotonic => libc::CLOCK_MONOTONIC,
-        } as clockid_t;
-
-        // Map the TimerEvent to libc::sigevent
-        let mut ev: libc::sigevent = unsafe { mem::zeroed() };
-        match event {
-            TimerEvent::None => ev.sigev_notify = libc::SIGEV_NONE,
-            TimerEvent::Signal(signo) => {
-                ev.sigev_signo = signo.0;
-                ev.sigev_notify = libc::SIGEV_SIGNAL;
-            }
-            TimerEvent::ThreadSignal(tid, signo) => {
-                ev.sigev_signo = signo.0;
-                ev.sigev_notify = libc::SIGEV_THREAD_ID;
-                ev.sigev_notify_thread_id = tid.0;
-            }
-            TimerEvent::ThisThreadSignal(signo) => {
-                ev.sigev_signo = signo.0;
-                ev.sigev_notify = libc::SIGEV_THREAD_ID;
-                ev.sigev_notify_thread_id = gettid().0;
-            }
-        }
-
-        // Create the timer
-        let mut timer: TimerT = unsafe { mem::zeroed() };
-        let rc = unsafe { timer_create(clkid, &mut ev, &mut timer) };
-        if rc != 0 {
-            Err(io::Error::last_os_error())
-        } else {
-            Ok(Timer { timer })
-        }
-    }
-
-    /// Arm a timer. This returns the previous timer specification.
-    pub fn arm(&mut self, spec: TimerSpec) -> io::Result<TimerSpec> {
-        let newspec = spec.to_itimerspec();
-        let mut oldspec = MaybeUninit::<libc::itimerspec>::uninit();
-
-        let rc = unsafe { timer_settime(self.timer, 0, &newspec, &mut *oldspec.as_mut_ptr()) };
-        if rc != 0 {
-            return Err(io::Error::last_os_error());
-        }
-
-        Ok(TimerSpec::from_itimerspec(unsafe { oldspec.assume_init() }))
-    }
-}
-
-impl Drop for Timer {
-    fn drop(&mut self) {
-        unsafe {
-            timer_delete(self.timer);
-        }
-    }
-}
-
-/// This is the signal number we use in our timeout implementations. We expect
-/// the signal handler for this signal to never be replaced by some other
-/// library. If this does happen, we need to find another signal. There should
-/// be plenty.
-/// Currently this is SIGRTMIN+4, the 5th real-time signal. glibc reserves the
-/// first two for pthread internals.
-pub const SIGTIMEOUT: Signal = Signal(32 + 4);
-
-// Our timeout handler does exactly nothing. We only need it to interrupt
-// system calls.
-extern "C" fn sig_timeout_handler(_: c_int) {}
-
-// See setup_timeout_handler().
-fn do_setup_timeout_handler() -> io::Result<()> {
-    // Unfortunately nix::sys::signal::Signal cannot represent real time
-    // signals, so we need to use libc instead...
-    //
-    // This WOULD be a nicer impl though:
-    //nix::sys::signal::sigaction(
-    //    SIGTIMEOUT,
-    //    nix::sys::signal::SigAction::new(
-    //        nix::sys::signal::SigHandler::Handler(sig_timeout_handler),
-    //        nix::sys::signal::SaFlags::empty(),
-    //        nix::sys::signal::SigSet::all()))
-    //    .map(|_|())
-
-    unsafe {
-        let mut sa_mask = MaybeUninit::<libc::sigset_t>::uninit();
-        if libc::sigemptyset(&mut *sa_mask.as_mut_ptr()) != 0
-            || libc::sigaddset(&mut *sa_mask.as_mut_ptr(), SIGTIMEOUT.0) != 0
-        {
-            return Err(io::Error::last_os_error());
-        }
-
-        let sa = libc::sigaction {
-            sa_sigaction:
-                // libc::sigaction uses `usize` for the function pointer...
-                sig_timeout_handler as *const extern "C" fn(i32) as usize,
-            sa_mask: sa_mask.assume_init(),
-            sa_flags: 0,
-            sa_restorer: None,
-        };
-        if libc::sigaction(SIGTIMEOUT.0, &sa, std::ptr::null_mut()) != 0 {
-            return Err(io::Error::last_os_error());
-        }
-    }
-    Ok(())
-}
-
-// The first time we unblock SIGTIMEOUT should cause approprate initialization:
-static SETUP_TIMEOUT_HANDLER: std::sync::Once = std::sync::Once::new();
-
-/// Setup our timeout-signal workflow. This establishes the signal handler for
-/// our `SIGTIMEOUT` and should be called once during initialization.
-#[inline]
-pub fn setup_timeout_handler() {
-    SETUP_TIMEOUT_HANDLER.call_once(|| {
-        // We unwrap here.
-        // If setting up this handler fails you have other problems already,
-        // plus, if setting up fails you can't *use* it either, so everything
-        // goes to die.
-        do_setup_timeout_handler().unwrap();
-    });
-}
-
-/// This guards the state of the timeout signal: We want it blocked usually.
-pub struct TimeoutBlockGuard(bool);
-impl Drop for TimeoutBlockGuard {
-    fn drop(&mut self) {
-        if self.0 {
-            block_timeout_signal();
-        } else {
-            unblock_timeout_signal().forget();
-        }
-    }
-}
-
-impl TimeoutBlockGuard {
-    /// Convenience helper to "forget" to restore the signal block mask.
-    #[inline(always)]
-    pub fn forget(self) {
-        std::mem::forget(self);
-    }
-
-    /// Convenience helper to trigger the guard behavior immediately.
-    #[inline(always)]
-    pub fn trigger(self) {
-        std::mem::drop(self); // be explicit here...
-    }
-}
-
-/// Unblock the timeout signal for the current thread. By default we block the
-/// signal this behavior should be restored when done using timeouts, therefor this
-/// returns a guard:
-#[inline(always)]
-pub fn unblock_timeout_signal() -> TimeoutBlockGuard {
-    // This calls std::sync::Once:
-    setup_timeout_handler();
-    //let mut set = nix::sys::signal::SigSet::empty();
-    //set.add(SIGTIMEOUT.0);
-    //set.thread_unblock()?;
-    //Ok(TimeoutBlockGuard{})
-    // Again, nix crate and its signal limitations...
-
-    // NOTE:
-    //   sigsetops(3) and pthread_sigmask(3) can only fail if invalid memory is
-    //   passed to the kernel, or signal numbers are "invalid", since we know
-    //   neither is the case we will panic on error...
-    let was_blocked = unsafe {
-        let mut mask = MaybeUninit::<libc::sigset_t>::uninit();
-        let mut oldset = MaybeUninit::<libc::sigset_t>::uninit();
-        if libc::sigemptyset(&mut *mask.as_mut_ptr()) != 0
-            || libc::sigaddset(&mut *mask.as_mut_ptr(), SIGTIMEOUT.0) != 0
-            || libc::pthread_sigmask(
-                libc::SIG_UNBLOCK,
-                &mask.assume_init(),
-                &mut *oldset.as_mut_ptr(),
-            ) != 0
-        {
-            panic!("Impossibly failed to unblock SIGTIMEOUT");
-            //return Err(io::Error::last_os_error());
-        }
-
-        libc::sigismember(&oldset.assume_init(), SIGTIMEOUT.0) == 1
-    };
-    TimeoutBlockGuard(was_blocked)
-}
-
-/// Block the timeout signal for the current thread. This is the default.
-#[inline(always)]
-pub fn block_timeout_signal() {
-    //let mut set = nix::sys::signal::SigSet::empty();
-    //set.add(SIGTIMEOUT);
-    //set.thread_block()
-    unsafe {
-        let mut mask = MaybeUninit::<libc::sigset_t>::uninit();
-        if libc::sigemptyset(&mut *mask.as_mut_ptr()) != 0
-            || libc::sigaddset(&mut *mask.as_mut_ptr(), SIGTIMEOUT.0) != 0
-            || libc::pthread_sigmask(libc::SIG_BLOCK, &mask.assume_init(), std::ptr::null_mut())
-                != 0
-        {
-            panic!("Impossibly failed to block SIGTIMEOUT");
-            //return Err(io::Error::last_os_error());
-        }
-    }
-}