Skip to content

Commit 0874cfa

Browse files
committed
Add OpenBSD compatibility to signals
1 parent 836c06d commit 0874cfa

File tree

1 file changed

+103
-90
lines changed

1 file changed

+103
-90
lines changed

src/sys/signal.rs

Lines changed: 103 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33

44
use libc;
55
use {Errno, Error, Result};
6-
use std::fmt;
7-
use std::fmt::Debug;
86
use std::mem;
97
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
108
use std::os::unix::io::RawFd;
119
use std::ptr;
1210

11+
#[cfg(not(target_os = "openbsd"))]
12+
pub use self::sigevent::*;
13+
1314
// Currently there is only one definition of c_int in libc, as well as only one
1415
// type for signal constants.
1516
// We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
@@ -488,102 +489,114 @@ pub enum SigevNotify {
488489
si_value: libc::intptr_t },
489490
}
490491

491-
/// Used to request asynchronous notification of the completion of certain
492-
/// events, such as POSIX AIO and timers.
493-
#[repr(C)]
494-
pub struct SigEvent {
495-
sigevent: libc::sigevent
496-
}
492+
#[cfg(not(target_os = "openbsd"))]
493+
mod sigevent {
494+
use libc;
495+
use std::mem;
496+
use std::ptr;
497+
use std::fmt::{self, Debug};
498+
use super::SigevNotify;
499+
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
500+
use super::type_of_thread_id;
501+
502+
/// Used to request asynchronous notification of the completion of certain
503+
/// events, such as POSIX AIO and timers.
504+
#[repr(C)]
505+
pub struct SigEvent {
506+
sigevent: libc::sigevent
507+
}
508+
509+
impl SigEvent {
510+
/// **Note:** this constructor does not allow the user to set the
511+
/// `sigev_notify_kevent_flags` field. That's considered ok because on FreeBSD
512+
/// at least those flags don't do anything useful. That field is part of a
513+
/// union that shares space with the more genuinely useful fields.
514+
///
515+
/// **Note:** This constructor also doesn't allow the caller to set the
516+
/// `sigev_notify_function` or `sigev_notify_attributes` fields, which are
517+
/// required for `SIGEV_THREAD`. That's considered ok because on no operating
518+
/// system is `SIGEV_THREAD` the most efficient way to deliver AIO
519+
/// notification. FreeBSD and DragonFly BSD programs should prefer `SIGEV_KEVENT`.
520+
/// Linux, Solaris, and portable programs should prefer `SIGEV_THREAD_ID` or
521+
/// `SIGEV_SIGNAL`. That field is part of a union that shares space with the
522+
/// more genuinely useful `sigev_notify_thread_id`
523+
pub fn new(sigev_notify: SigevNotify) -> SigEvent {
524+
let mut sev = unsafe { mem::zeroed::<libc::sigevent>()};
525+
sev.sigev_notify = match sigev_notify {
526+
SigevNotify::SigevNone => libc::SIGEV_NONE,
527+
SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
528+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
529+
SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
530+
#[cfg(target_os = "freebsd")]
531+
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
532+
#[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
533+
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
534+
#[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
535+
SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined
536+
};
537+
sev.sigev_signo = match sigev_notify {
538+
SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
539+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
540+
SigevNotify::SigevKevent{ kq, ..} => kq,
541+
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
542+
SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
543+
_ => 0
544+
};
545+
sev.sigev_value.sival_ptr = match sigev_notify {
546+
SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
547+
SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
548+
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
549+
SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
550+
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
551+
SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
552+
};
553+
SigEvent::set_tid(&mut sev, &sigev_notify);
554+
SigEvent{sigevent: sev}
555+
}
497556

498-
impl SigEvent {
499-
// Note: this constructor does not allow the user to set the
500-
// sigev_notify_kevent_flags field. That's considered ok because on FreeBSD
501-
// at least those flags don't do anything useful. That field is part of a
502-
// union that shares space with the more genuinely useful
503-
// Note: This constructor also doesn't allow the caller to set the
504-
// sigev_notify_function or sigev_notify_attributes fields, which are
505-
// required for SIGEV_THREAD. That's considered ok because on no operating
506-
// system is SIGEV_THREAD the most efficient way to deliver AIO
507-
// notification. FreeBSD and Dragonfly programs should prefer SIGEV_KEVENT.
508-
// Linux, Solaris, and portable programs should prefer SIGEV_THREAD_ID or
509-
// SIGEV_SIGNAL. That field is part of a union that shares space with the
510-
// more genuinely useful sigev_notify_thread_id
511-
pub fn new(sigev_notify: SigevNotify) -> SigEvent {
512-
let mut sev = unsafe { mem::zeroed::<libc::sigevent>()};
513-
sev.sigev_notify = match sigev_notify {
514-
SigevNotify::SigevNone => libc::SIGEV_NONE,
515-
SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
516-
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
517-
SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
518-
#[cfg(target_os = "freebsd")]
519-
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
520-
#[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
521-
SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
522-
#[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
523-
SigevNotify::SigevThreadId{..} => 4 // No SIGEV_THREAD_ID defined
524-
};
525-
sev.sigev_signo = match sigev_notify {
526-
SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
527-
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
528-
SigevNotify::SigevKevent{ kq, ..} => kq,
529-
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
530-
SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
531-
_ => 0
532-
};
533-
sev.sigev_value.sival_ptr = match sigev_notify {
534-
SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
535-
SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
536-
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
537-
SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
538-
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
539-
SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
540-
};
541-
SigEvent::set_tid(&mut sev, &sigev_notify);
542-
SigEvent{sigevent: sev}
543-
}
557+
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
558+
fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
559+
sev.sigev_notify_thread_id = match sigev_notify {
560+
&SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
561+
_ => 0 as type_of_thread_id
562+
};
563+
}
544564

545-
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
546-
fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
547-
sev.sigev_notify_thread_id = match sigev_notify {
548-
&SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
549-
_ => 0 as type_of_thread_id
550-
};
551-
}
565+
#[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
566+
fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
567+
}
552568

553-
#[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
554-
fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
569+
pub fn sigevent(&self) -> libc::sigevent {
570+
self.sigevent
571+
}
555572
}
556573

557-
pub fn sigevent(&self) -> libc::sigevent {
558-
self.sigevent
559-
}
560-
}
574+
impl Debug for SigEvent {
575+
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
576+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
577+
fmt.debug_struct("SigEvent")
578+
.field("sigev_notify", &self.sigevent.sigev_notify)
579+
.field("sigev_signo", &self.sigevent.sigev_signo)
580+
.field("sigev_value", &self.sigevent.sigev_value.sival_ptr)
581+
.field("sigev_notify_thread_id",
582+
&self.sigevent.sigev_notify_thread_id)
583+
.finish()
584+
}
561585

562-
impl Debug for SigEvent {
563-
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
564-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
565-
fmt.debug_struct("SigEvent")
566-
.field("sigev_notify", &self.sigevent.sigev_notify)
567-
.field("sigev_signo", &self.sigevent.sigev_signo)
568-
.field("sigev_value", &self.sigevent.sigev_value.sival_ptr)
569-
.field("sigev_notify_thread_id",
570-
&self.sigevent.sigev_notify_thread_id)
571-
.finish()
572-
}
573-
574-
#[cfg(not(any(target_os = "linux", target_os = "freebsd")))]
575-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
576-
fmt.debug_struct("SigEvent")
577-
.field("sigev_notify", &self.sigevent.sigev_notify)
578-
.field("sigev_signo", &self.sigevent.sigev_signo)
579-
.field("sigev_value", &self.sigevent.sigev_value.sival_ptr)
580-
.finish()
586+
#[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
587+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
588+
fmt.debug_struct("SigEvent")
589+
.field("sigev_notify", &self.sigevent.sigev_notify)
590+
.field("sigev_signo", &self.sigevent.sigev_signo)
591+
.field("sigev_value", &self.sigevent.sigev_value.sival_ptr)
592+
.finish()
593+
}
581594
}
582-
}
583595

584-
impl<'a> From<&'a libc::sigevent> for SigEvent {
585-
fn from(sigevent: &libc::sigevent) -> Self {
586-
SigEvent{ sigevent: sigevent.clone() }
596+
impl<'a> From<&'a libc::sigevent> for SigEvent {
597+
fn from(sigevent: &libc::sigevent) -> Self {
598+
SigEvent{ sigevent: sigevent.clone() }
599+
}
587600
}
588601
}
589602

0 commit comments

Comments
 (0)