Commit ecd8aca6 authored by jD91mZM2's avatar jD91mZM2

Basic signal support

parent 7b8e7feb
Pipeline #773 failed with stages
in 5 minutes and 9 seconds
#define SIG_ERR -1ULL
#define NSIG 64
// darn cbindgen
typedef unsigned long sigset_t[NSIG / (8 * sizeof(unsigned long))];
......@@ -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;
......
#![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;
......
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"
......
//! 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]
......
#[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;
......
#[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 \
......
Raising...
Signal handler called!
Raised.
#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.");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment