blob: b28c4432842696375fc4287859890e6c25e43661 [file] [log] [blame]
// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Provides abstraction for needed libc functionality that isn't included in
//! sys_util. Generally Sirenia code outside of this module shouldn't directly
//! interact with the libc package.
//!
//! TODO(b/162502718) Move this over to crosvm/sys_util
use std::io;
use std::mem::MaybeUninit;
use std::ptr::null_mut;
use libc::{self, c_int, sigfillset, sigprocmask, sigset_t, wait, ECHILD, SIG_BLOCK, SIG_UNBLOCK};
pub fn errno() -> c_int {
io::Error::last_os_error().raw_os_error().unwrap()
}
pub fn wait_for_child() -> bool {
let mut ret: c_int = 0;
// This is safe because it merely blocks execution until a process
// life-cycle event occurs, or there are no child processes to wait on.
if unsafe { wait(&mut ret) } == -1 && errno() == ECHILD {
return false;
}
true
}
pub fn block_all_signals() {
let mut signal_set: sigset_t;
// This is safe as long as nothing else is depending on receiving a signal
// to guarantee safety.
unsafe {
signal_set = MaybeUninit::zeroed().assume_init();
// Block signals since init should not die or return.
sigfillset(&mut signal_set);
sigprocmask(SIG_BLOCK, &signal_set, null_mut());
}
}
pub fn unblock_all_signals() {
let mut signal_set: sigset_t;
// This is safe because it doesn't allocate or free any structures.
unsafe {
signal_set = MaybeUninit::zeroed().assume_init();
// Block signals since init should not die or return.
sigfillset(&mut signal_set);
sigprocmask(SIG_UNBLOCK, &signal_set, null_mut());
}
}
/// Forks the process and returns the child pid or 0 for the child process.
///
/// # Safety
///
/// This is only safe if the open file descriptors are intended to be cloned
/// into the child process. The child should explicitly close any file
/// descriptors that are not intended to be kept open.
pub unsafe fn fork() -> Result<i32, io::Error> {
let ret: c_int = libc::fork();
if ret < 0 {
Err(io::Error::last_os_error())
} else {
Ok(ret)
}
}