Basic signal support
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
#define SIG_ERR -1ULL
|
||||
|
||||
#define NSIG 64
|
||||
|
||||
// darn cbindgen
|
||||
typedef unsigned long sigset_t[NSIG / (8 * sizeof(unsigned long))];
|
||||
+2
-2
@@ -25,9 +25,9 @@ typedef long ssize_t;
|
||||
|
||||
typedef long time_t;
|
||||
|
||||
typedef int useconds_t;
|
||||
typedef unsigned int useconds_t;
|
||||
|
||||
typedef long suseconds_t;
|
||||
typedef int suseconds_t;
|
||||
|
||||
typedef long clock_t;
|
||||
|
||||
|
||||
+19
-2
@@ -1,7 +1,7 @@
|
||||
#![no_std]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![feature(alloc, allocator_api, const_vec_new)]
|
||||
//TODO #![feature(thread_local)]
|
||||
#![cfg_attr(target_os = "redox", feature(thread_local))]
|
||||
|
||||
#[cfg_attr(target_os = "redox", macro_use)]
|
||||
extern crate alloc;
|
||||
@@ -36,7 +36,7 @@ mod sys;
|
||||
pub mod types;
|
||||
|
||||
use alloc::Vec;
|
||||
use core::{fmt, ptr};
|
||||
use core::{fmt, mem, ptr};
|
||||
|
||||
use types::*;
|
||||
|
||||
@@ -49,16 +49,33 @@ pub const SOCK_DGRAM: c_int = 2;
|
||||
pub const SOCK_NONBLOCK: c_int = 0o4000;
|
||||
pub const SOCK_CLOEXEC: c_int = 0o2000000;
|
||||
|
||||
pub const SIG_BLOCK: c_int = 0;
|
||||
pub const SIG_UNBLOCK: c_int = 1;
|
||||
pub const SIG_SETMASK: c_int = 2;
|
||||
|
||||
pub type in_addr_t = [u8; 4];
|
||||
pub type in_port_t = u16;
|
||||
pub type sa_family_t = u16;
|
||||
pub type socklen_t = u32;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct sockaddr {
|
||||
pub sa_family: sa_family_t,
|
||||
pub data: [c_char; 14],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct sigaction {
|
||||
pub sa_handler: extern "C" fn(c_int),
|
||||
pub sa_flags: c_ulong,
|
||||
pub sa_restorer: unsafe extern "C" fn(),
|
||||
pub sa_mask: sigset_t
|
||||
}
|
||||
|
||||
const NSIG: usize = 64;
|
||||
|
||||
pub type sigset_t = [c_ulong; NSIG / (8 * mem::size_of::<c_ulong>())];
|
||||
|
||||
//TODO #[thread_local]
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[no_mangle]
|
||||
|
||||
@@ -259,6 +259,17 @@ pub fn pipe(fildes: &mut [c_int]) -> c_int {
|
||||
e(unsafe { syscall!(PIPE2, fildes.as_mut_ptr(), 0) }) as c_int
|
||||
}
|
||||
|
||||
pub fn raise(sig: c_int) -> c_int {
|
||||
let tid = e(unsafe { syscall!(GETTID) }) as pid_t;
|
||||
let ret = if tid == !0 {
|
||||
-1
|
||||
} else {
|
||||
e(unsafe { syscall!(TKILL, tid, sig) }) as c_int
|
||||
};
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t {
|
||||
e(unsafe { syscall!(READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t
|
||||
}
|
||||
@@ -338,6 +349,14 @@ pub fn shutdown(socket: c_int, how: c_int) -> c_int {
|
||||
e(unsafe { syscall!(SHUTDOWN, socket, how) }) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int {
|
||||
e(syscall!(RT_SIGACTION, sig, act, oact, mem::size_of::<sigset_t>())) as c_int
|
||||
}
|
||||
|
||||
pub fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int {
|
||||
e(unsafe { syscall!(RT_SIGPROCMASK, how, set, oset, mem::size_of::<sigset_t>()) }) as c_int
|
||||
}
|
||||
|
||||
pub fn stat(file: *const c_char, buf: *mut stat) -> c_int {
|
||||
e(unsafe { syscall!(NEWFSTATAT, AT_FDCWD, file, buf, 0) }) as c_int
|
||||
}
|
||||
|
||||
@@ -12,6 +12,15 @@ use syscall::{self, Result};
|
||||
use types::*;
|
||||
use *;
|
||||
|
||||
#[thread_local]
|
||||
static mut SIG_HANDLER: Option<extern "C" fn(c_int)> = None;
|
||||
|
||||
extern "C" fn sig_handler(sig: usize) {
|
||||
if let Some(ref callback) = unsafe { SIG_HANDLER } {
|
||||
callback(sig as c_int);
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct SockData {
|
||||
port: in_port_t,
|
||||
@@ -483,6 +492,10 @@ pub fn pipe(fds: &mut [c_int]) -> c_int {
|
||||
res as c_int
|
||||
}
|
||||
|
||||
pub fn raise(sig: c_int) -> c_int {
|
||||
kill(getpid(), sig)
|
||||
}
|
||||
|
||||
pub fn read(fd: c_int, buf: &mut [u8]) -> ssize_t {
|
||||
e(syscall::read(fd as usize, buf)) as ssize_t
|
||||
}
|
||||
@@ -585,6 +598,49 @@ pub fn shutdown(socket: c_int, how: c_int) -> c_int {
|
||||
-1
|
||||
}
|
||||
|
||||
pub unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int {
|
||||
if !oact.is_null() {
|
||||
// Assumes the last sigaction() call was made by relibc and not a different one
|
||||
if let Some(callback) = SIG_HANDLER {
|
||||
(*oact).sa_handler = callback;
|
||||
}
|
||||
}
|
||||
let act = if act.is_null() {
|
||||
None
|
||||
} else {
|
||||
SIG_HANDLER = Some((*act).sa_handler);
|
||||
let m = (*act).sa_mask;
|
||||
Some(syscall::SigAction {
|
||||
sa_handler: sig_handler,
|
||||
sa_mask: [m[0] as u64, 0],
|
||||
sa_flags: (*act).sa_flags as usize
|
||||
})
|
||||
};
|
||||
let mut old = syscall::SigAction::default();
|
||||
let ret = e(syscall::sigaction(
|
||||
sig as usize,
|
||||
act.as_ref(),
|
||||
if oact.is_null() { None } else { Some(&mut old) }
|
||||
)) as c_int;
|
||||
if !oact.is_null() {
|
||||
let m = old.sa_mask;
|
||||
(*oact).sa_mask = [m[0] as c_ulong];
|
||||
(*oact).sa_flags = old.sa_flags as c_ulong;
|
||||
}
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int {
|
||||
let _ = write!(
|
||||
::FileWriter(2),
|
||||
"unimplemented: sigprocmask({}, {:p}, {:p})",
|
||||
how,
|
||||
set,
|
||||
oset
|
||||
);
|
||||
-1
|
||||
}
|
||||
|
||||
pub fn stat(path: *const c_char, buf: *mut stat) -> c_int {
|
||||
let path = unsafe { c_str(path) };
|
||||
match syscall::open(path, O_RDONLY) {
|
||||
|
||||
@@ -61,8 +61,8 @@ pub type nlink_t = usize;
|
||||
pub type blksize_t = isize;
|
||||
pub type blkcnt_t = u64;
|
||||
|
||||
pub type useconds_t = i32;
|
||||
pub type suseconds_t = i64;
|
||||
pub type useconds_t = c_uint;
|
||||
pub type suseconds_t = c_int;
|
||||
|
||||
pub type clock_t = i64;
|
||||
pub type clockid_t = i32;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
sys_includes = ["stdint.h", "sys/types.h"]
|
||||
sys_includes = ["stdint.h", "sys/types.h", "bits/signal.h"]
|
||||
include_guard = "_SIGNAL_H"
|
||||
style = "Tag"
|
||||
language = "C"
|
||||
|
||||
+56
-20
@@ -1,7 +1,9 @@
|
||||
//! signal implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/signal.h.html
|
||||
|
||||
#![no_std]
|
||||
#![feature(asm, const_fn, core_intrinsics, global_asm)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate platform;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
@@ -12,22 +14,29 @@ pub mod sys;
|
||||
#[path = "redox.rs"]
|
||||
pub mod sys;
|
||||
|
||||
const SIG_ERR: usize = !0;
|
||||
|
||||
pub const SIG_BLOCK: c_int = 0;
|
||||
pub const SIG_UNBLOCK: c_int = 1;
|
||||
pub const SIG_SETMASK: c_int = 2;
|
||||
|
||||
pub use sys::*;
|
||||
|
||||
use platform::types::*;
|
||||
|
||||
// Need both here and in platform because cbindgen :(
|
||||
#[repr(C)]
|
||||
#[derive(Clone)]
|
||||
pub struct sigaction {
|
||||
pub sa_handler: extern "C" fn(usize),
|
||||
pub sa_mask: sigset_t,
|
||||
pub sa_flags: usize,
|
||||
pub sa_handler: extern "C" fn(c_int),
|
||||
pub sa_flags: c_ulong,
|
||||
pub sa_restorer: unsafe extern "C" fn(),
|
||||
pub sa_mask: sigset_t
|
||||
}
|
||||
|
||||
pub type sigset_t = sys_sigset_t;
|
||||
const NSIG: usize = 64;
|
||||
|
||||
pub use sys::*;
|
||||
|
||||
use core::{mem, ptr};
|
||||
use platform::types::*;
|
||||
use platform::sigset_t;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn kill(pid: pid_t, sig: c_int) -> c_int {
|
||||
@@ -39,14 +48,22 @@ pub extern "C" fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
|
||||
platform::killpg(pgrp, sig)
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn raise(sig: c_int) -> c_int {
|
||||
unimplemented!();
|
||||
platform::raise(sig)
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn sigaction(sig: c_int, act: *const sigaction, oact: *const sigaction) -> c_int {
|
||||
unimplemented!();
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int {
|
||||
let mut _sigaction = None;
|
||||
let ptr = if !act.is_null() {
|
||||
_sigaction = Some((*act).clone());
|
||||
_sigaction.as_mut().unwrap().sa_flags |= SA_RESTORER as c_ulong;
|
||||
_sigaction.as_mut().unwrap() as *mut _ as *mut platform::sigaction
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
};
|
||||
platform::sigaction(sig, ptr, oact as *mut platform::sigaction)
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
@@ -64,9 +81,12 @@ pub extern "C" fn sigemptyset(set: *mut sigset_t) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sigfillset(set: *mut sigset_t) -> c_int {
|
||||
unimplemented!();
|
||||
for i in unsafe { &mut (*set) } {
|
||||
*i = c_ulong::max_value();
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
@@ -89,9 +109,25 @@ pub extern "C" fn sigismember(set: *const sigset_t, signo: c_int) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn signal(sig: c_int, func: fn(c_int)) -> fn(c_int) {
|
||||
unimplemented!();
|
||||
extern "C" {
|
||||
// Defined in assembly inside platform/x/mod.rs
|
||||
fn __restore_rt();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn signal(sig: c_int, func: extern "C" fn(c_int)) -> extern "C" fn(c_int) {
|
||||
let sa = sigaction {
|
||||
sa_handler: func,
|
||||
sa_flags: SA_RESTART as c_ulong,
|
||||
sa_restorer: __restore_rt,
|
||||
sa_mask: sigset_t::default()
|
||||
};
|
||||
let mut old_sa = unsafe { mem::uninitialized() };
|
||||
if unsafe { sigaction(sig, &sa, &mut old_sa) } < 0 {
|
||||
mem::forget(old_sa);
|
||||
return unsafe { mem::transmute(SIG_ERR) };
|
||||
}
|
||||
old_sa.sa_handler
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
@@ -104,9 +140,9 @@ pub extern "C" fn sigpending(set: *mut sigset_t) -> c_int {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int {
|
||||
unimplemented!();
|
||||
platform::sigprocmask(how, set, oset)
|
||||
}
|
||||
|
||||
// #[no_mangle]
|
||||
|
||||
+15
-4
@@ -1,7 +1,18 @@
|
||||
#[repr(C)]
|
||||
pub struct sys_sigset_t {
|
||||
pub bits: [u64; 16],
|
||||
}
|
||||
// Needs to be defined in assembly because it can't have a function prologue
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
global_asm!("
|
||||
.global __restore_rt
|
||||
__restore_rt:
|
||||
mov $15, %rax # <- rax is register, 15 is RT_SIGRETURN
|
||||
syscall
|
||||
");
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
global_asm!("
|
||||
.global __restore_rt
|
||||
__restore_rt:
|
||||
mov x8, #139 # <- x8 is register, 139 is RT_SIGRETURN
|
||||
svc 0
|
||||
");
|
||||
|
||||
pub const SIGHUP: usize = 1;
|
||||
pub const SIGINT: usize = 2;
|
||||
|
||||
+15
-4
@@ -1,7 +1,18 @@
|
||||
#[repr(C)]
|
||||
pub struct sys_sigset_t {
|
||||
pub bits: [u64; 2],
|
||||
}
|
||||
// Needs to be defined in assembly because it can't have a function prologue
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
global_asm!("
|
||||
.global __restore_rt
|
||||
__restore_rt:
|
||||
mov $119, %rax # <- rax is register, 119 is SIGRETURN
|
||||
int $0x80
|
||||
");
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
global_asm!("
|
||||
.global __restore_rt
|
||||
__restore_rt:
|
||||
mov x8, #119 # <- x8 is register, 119 is SIGRETURN
|
||||
svc 0
|
||||
");
|
||||
|
||||
pub const SIGHUP: usize = 1;
|
||||
pub const SIGINT: usize = 2;
|
||||
|
||||
@@ -449,8 +449,8 @@ pub extern "C" fn unlink(path: *const c_char) -> c_int {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn usleep(useconds: useconds_t) -> c_int {
|
||||
let rqtp = timespec {
|
||||
tv_sec: 0,
|
||||
tv_nsec: (useconds * 1000).into(),
|
||||
tv_sec: (useconds / 1_000_000) as i64,
|
||||
tv_nsec: ((useconds % 1000) * 1000) as i64,
|
||||
};
|
||||
let rmtp = ptr::null_mut();
|
||||
platform::nanosleep(&rqtp, rmtp)
|
||||
|
||||
@@ -11,6 +11,7 @@ fcntl/fcntl
|
||||
locale
|
||||
math
|
||||
setjmp
|
||||
signal
|
||||
stdio/all
|
||||
stdio/freopen
|
||||
stdio/fwrite
|
||||
|
||||
@@ -10,6 +10,7 @@ EXPECT_BINS=\
|
||||
locale \
|
||||
math \
|
||||
setjmp \
|
||||
signal \
|
||||
stdio/all \
|
||||
stdio/freopen \
|
||||
stdio/fwrite \
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
Raising...
|
||||
Signal handler called!
|
||||
Raised.
|
||||
@@ -0,0 +1,24 @@
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
void handler(int sig) {
|
||||
puts("Signal handler called!");
|
||||
}
|
||||
|
||||
int main() {
|
||||
if (((size_t) signal(SIGUSR1, &handler)) == SIG_ERR) {
|
||||
puts("Signal error!");
|
||||
printf("%d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
puts("Raising...");
|
||||
if (raise(SIGUSR1)) {
|
||||
puts("Raise error!");
|
||||
printf("%d\n", errno);
|
||||
return 1;
|
||||
}
|
||||
puts("Raised.");
|
||||
}
|
||||
Reference in New Issue
Block a user