Skip to content

Commit

Permalink
Merge pull request #3630 from asomers/sigevent2
Browse files Browse the repository at this point in the history
Fix the definition of sigevent on FreeBSD and Linux
  • Loading branch information
tgross35 authored Nov 25, 2024
2 parents 951cab5 + d255379 commit 0808995
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 104 deletions.
17 changes: 14 additions & 3 deletions libc-test/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2080,6 +2080,9 @@ fn test_android(target: &str) {
("Elf32_Phdr", "p_type") => true,
("Elf64_Phdr", "p_type") => true,

// _sigev_un is an anonymous union
("sigevent", "_sigev_un") => true,

// this is actually a union on linux, so we can't represent it well and
// just insert some padding.
("siginfo_t", "_pad") => true,
Expand Down Expand Up @@ -2671,7 +2674,7 @@ fn test_freebsd(target: &str) {
cfg.volatile_item(|i| {
use ctest::VolatileItemKind::*;
match i {
// aio_buf is a volatile void** but since we cannot express that in
// aio_buf is a volatile void* but since we cannot express that in
// Rust types, we have to explicitly tell the checker about it here:
StructField(ref n, ref f) if n == "aiocb" && f == "aio_buf" => true,
_ => false,
Expand All @@ -2691,6 +2694,9 @@ fn test_freebsd(target: &str) {
// not available until FreeBSD 12, and is an anonymous union there.
("xucred", "cr_pid__c_anonymous_union") => true,

// Anonymous union
("sigevent", "_sigev_un") => true,

// m_owner field is a volatile __lwpid_t
("umutex", "m_owner") => true,
// c_has_waiters field is a volatile int32_t
Expand Down Expand Up @@ -2883,6 +2889,9 @@ fn test_emscripten(target: &str) {
});

cfg.skip_struct(move |ty| {
if ty.starts_with("__c_anonymous_") {
return true;
}
match ty {
// This is actually a union, not a struct
"sigval" => true,
Expand Down Expand Up @@ -2968,6 +2977,8 @@ fn test_emscripten(target: &str) {
});

cfg.skip_field(move |struct_, field| {
// _sigev_un is an anonymous union
(struct_ == "sigevent" && field == "_sigev_un") ||
// this is actually a union on linux, so we can't represent it well and
// just insert some padding.
(struct_ == "siginfo_t" && field == "_pad") ||
Expand Down Expand Up @@ -4359,8 +4370,8 @@ fn test_linux(target: &str) {
(musl && struct_ == "glob_t" && field == "gl_flags") ||
// musl seems to define this as an *anonymous* bitfield
(musl && struct_ == "statvfs" && field == "__f_unused") ||
// sigev_notify_thread_id is actually part of a sigev_un union
(struct_ == "sigevent" && field == "sigev_notify_thread_id") ||
// _sigev_un is an anonymous union
(struct_ == "sigevent" && field == "_sigev_un") ||
// signalfd had SIGSYS fields added in Linux 4.18, but no libc release
// has them yet.
(struct_ == "signalfd_siginfo" && (field == "ssi_addr_lsb" ||
Expand Down
75 changes: 37 additions & 38 deletions src/unix/bsd/freebsdlike/freebsd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,20 +236,10 @@ impl ::Clone for devstat_select_mode {
}

s! {
pub struct aiocb {
pub aio_fildes: ::c_int,
pub aio_offset: ::off_t,
pub aio_buf: *mut ::c_void,
pub aio_nbytes: ::size_t,
__unused1: [::c_int; 2],
__unused2: *mut ::c_void,
pub aio_lio_opcode: ::c_int,
pub aio_reqprio: ::c_int,
// unused 3 through 5 are the __aiocb_private structure
__unused3: ::c_long,
__unused4: ::c_long,
__unused5: *mut ::c_void,
pub aio_sigevent: sigevent,
pub struct __c_anonymous_sigev_thread {
pub _function: Option<extern "C" fn(::sigval) -> *mut ::c_void>,
//pub _function: *mut ::c_void, // Actually a function pointer
pub _attribute: *mut ::pthread_attr_t,
}

pub struct jail {
Expand Down Expand Up @@ -1351,6 +1341,36 @@ s! {
}

s_no_extra_traits! {
#[cfg_attr(feature = "extra_traits", derive(Debug))]
pub struct __aiocb_private {
status: ::c_long,
error: ::c_long,
spare: *mut ::c_void,
}

#[cfg_attr(feature = "extra_traits", derive(Debug))]
pub struct aiocb {
pub aio_fildes: ::c_int,
pub aio_offset: ::off_t,
pub aio_buf: *mut ::c_void,
pub aio_nbytes: ::size_t,
__spare__: [::c_int; 2],
__spare2__: *mut ::c_void,
pub aio_lio_opcode: ::c_int,
pub aio_reqprio: ::c_int,
_aiocb_private: __aiocb_private,
pub aio_sigevent: sigevent,
}

// Can't correctly impl Debug for unions
#[allow(missing_debug_implementations)]
pub union __c_anonymous_sigev_un {
pub _threadid: ::__lwpid_t,
pub _sigev_thread: __c_anonymous_sigev_thread,
pub _kevent_flags: ::c_ushort,
__spare__: [::c_long; 8],
}

pub struct utmpx {
pub ut_type: ::c_short,
pub ut_tv: ::timeval,
Expand Down Expand Up @@ -1398,12 +1418,7 @@ s_no_extra_traits! {
pub sigev_notify: ::c_int,
pub sigev_signo: ::c_int,
pub sigev_value: ::sigval,
//The rest of the structure is actually a union. We expose only
//sigev_notify_thread_id because it's the most useful union member.
pub sigev_notify_thread_id: ::lwpid_t,
#[cfg(target_pointer_width = "64")]
__unused1: ::c_int,
__unused2: [::c_long; 7],
pub _sigev_un: __c_anonymous_sigev_un,
}

pub struct ptsstat {
Expand Down Expand Up @@ -1819,33 +1834,17 @@ cfg_if! {
}
}

impl PartialEq for sigevent {
fn eq(&self, other: &sigevent) -> bool {
self.sigev_notify == other.sigev_notify
&& self.sigev_signo == other.sigev_signo
&& self.sigev_value == other.sigev_value
&& self.sigev_notify_thread_id == other.sigev_notify_thread_id
}
}
impl Eq for sigevent {}
impl ::fmt::Debug for sigevent {
fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
f.debug_struct("sigevent")
.field("sigev_notify", &self.sigev_notify)
.field("sigev_signo", &self.sigev_signo)
.field("sigev_value", &self.sigev_value)
.field("sigev_notify_thread_id", &self.sigev_notify_thread_id)
// Skip _sigev_un, since we can't guarantee that it will be
// properly initialized.
.finish()
}
}
impl ::hash::Hash for sigevent {
fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
self.sigev_notify.hash(state);
self.sigev_signo.hash(state);
self.sigev_value.hash(state);
self.sigev_notify_thread_id.hash(state);
}
}

impl PartialEq for ptsstat {
fn eq(&self, other: &ptsstat) -> bool {
Expand Down
40 changes: 22 additions & 18 deletions src/unix/linux_like/linux/gnu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,6 @@ cfg_if! {
}

s! {
pub struct aiocb {
pub aio_fildes: ::c_int,
pub aio_lio_opcode: ::c_int,
pub aio_reqprio: ::c_int,
pub aio_buf: *mut ::c_void,
pub aio_nbytes: ::size_t,
pub aio_sigevent: ::sigevent,
__next_prio: *mut aiocb,
__abs_prio: ::c_int,
__policy: ::c_int,
__error_code: ::c_int,
__return_value: ::ssize_t,
pub aio_offset: off_t,
#[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))]
__unused1: [::c_char; 4],
__glibc_reserved: [::c_char; 32],
}

pub struct __exit_status {
pub e_termination: ::c_short,
pub e_exit: ::c_short,
Expand Down Expand Up @@ -510,6 +492,28 @@ impl siginfo_t {
}
}

s_no_extra_traits! {
#[cfg_attr(feature = "extra_traits", derive(Debug))]
pub struct aiocb {
pub aio_fildes: ::c_int,
pub aio_lio_opcode: ::c_int,
pub aio_reqprio: ::c_int,
pub aio_buf: *mut ::c_void,
pub aio_nbytes: ::size_t,
pub aio_sigevent: ::sigevent,
__next_prio: *mut aiocb,
__abs_prio: ::c_int,
__policy: ::c_int,
__error_code: ::c_int,
__return_value: ::ssize_t,
// FIXME(off64): visible fields depend on __USE_FILE_OFFSET64
pub aio_offset: off_t,
#[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))]
__pad: [::c_char; 4],
__glibc_reserved: [::c_char; 32],
}
}

// Internal, for casts to access union fields
#[repr(C)]
struct sifields_sigchld {
Expand Down
42 changes: 22 additions & 20 deletions src/unix/linux_like/linux/musl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,26 +119,6 @@ impl siginfo_t {
}

s! {
pub struct aiocb {
pub aio_fildes: ::c_int,
pub aio_lio_opcode: ::c_int,
pub aio_reqprio: ::c_int,
pub aio_buf: *mut ::c_void,
pub aio_nbytes: ::size_t,
pub aio_sigevent: ::sigevent,
__td: *mut ::c_void,
__lock: [::c_int; 2],
__err: ::c_int,
__ret: ::ssize_t,
pub aio_offset: off_t,
__next: *mut ::c_void,
__prev: *mut ::c_void,
#[cfg(target_pointer_width = "32")]
__dummy4: [::c_char; 24],
#[cfg(target_pointer_width = "64")]
__dummy4: [::c_char; 16],
}

pub struct sigaction {
pub sa_sigaction: ::sighandler_t,
pub sa_mask: ::sigset_t,
Expand Down Expand Up @@ -496,6 +476,28 @@ s! {
}

s_no_extra_traits! {
#[cfg_attr(feature = "extra_traits", derive(Debug))]
pub struct aiocb {
pub aio_fildes: ::c_int,
pub aio_lio_opcode: ::c_int,
pub aio_reqprio: ::c_int,
pub aio_buf: *mut ::c_void,
pub aio_nbytes: ::size_t,
pub aio_sigevent: ::sigevent,
__td: *mut ::c_void,
__lock: [::c_int; 2],
__err: ::c_int,
__ret: ::ssize_t,
pub aio_offset: off_t,
__next: *mut ::c_void,
__prev: *mut ::c_void,
// FIXME(ctest): length should be `32 - 2 * core::mem::size_of::<*const ()>()`
#[cfg(target_pointer_width = "32")]
__dummy4: [::c_char; 24],
#[cfg(target_pointer_width = "64")]
__dummy4: [::c_char; 16],
}

pub struct sysinfo {
pub uptime: ::c_ulong,
pub loads: [::c_ulong; 3],
Expand Down
51 changes: 26 additions & 25 deletions src/unix/linux_like/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ missing! {
}

s! {
pub struct __c_anonymous_sigev_thread {
pub _function: Option<extern "C" fn(::sigval) -> *mut ::c_void>,
pub _attribute: *mut ::pthread_attr_t,
}

pub struct in_addr {
pub s_addr: ::in_addr_t,
}
Expand Down Expand Up @@ -261,6 +266,14 @@ s_no_extra_traits! {
pub u64: u64,
}

// Can't correctly impl Debug for unions
#[allow(missing_debug_implementations)]
pub union __c_anonymous_sigev_un {
_pad: [::c_int; SIGEV_PAD_SIZE],
pub _tid: ::c_int,
pub _sigev_thread: __c_anonymous_sigev_thread,
}

pub struct sockaddr_un {
pub sun_family: sa_family_t,
pub sun_path: [::c_char; 108],
Expand Down Expand Up @@ -288,13 +301,7 @@ s_no_extra_traits! {
pub sigev_value: ::sigval,
pub sigev_signo: ::c_int,
pub sigev_notify: ::c_int,
// Actually a union. We only expose sigev_notify_thread_id because it's
// the most useful member
pub sigev_notify_thread_id: ::c_int,
#[cfg(target_pointer_width = "64")]
__unused1: [::c_int; 11],
#[cfg(target_pointer_width = "32")]
__unused1: [::c_int; 12],
pub _sigev_un: __c_anonymous_sigev_un,
}
}

Expand Down Expand Up @@ -441,33 +448,17 @@ cfg_if! {
}
}

impl PartialEq for sigevent {
fn eq(&self, other: &sigevent) -> bool {
self.sigev_value == other.sigev_value
&& self.sigev_signo == other.sigev_signo
&& self.sigev_notify == other.sigev_notify
&& self.sigev_notify_thread_id == other.sigev_notify_thread_id
}
}
impl Eq for sigevent {}
impl ::fmt::Debug for sigevent {
fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
f.debug_struct("sigevent")
.field("sigev_value", &self.sigev_value)
.field("sigev_signo", &self.sigev_signo)
.field("sigev_notify", &self.sigev_notify)
.field("sigev_notify_thread_id", &self.sigev_notify_thread_id)
// Skip _sigev_un, since we can't guarantee that it will be
// properly initialized.
.finish()
}
}
impl ::hash::Hash for sigevent {
fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
self.sigev_value.hash(state);
self.sigev_signo.hash(state);
self.sigev_notify.hash(state);
self.sigev_notify_thread_id.hash(state);
}
}
}
}

Expand Down Expand Up @@ -582,6 +573,16 @@ pub const SIGPIPE: ::c_int = 13;
pub const SIGALRM: ::c_int = 14;
pub const SIGTERM: ::c_int = 15;

const SIGEV_MAX_SIZE: usize = 64;
cfg_if! {
if #[cfg(target_pointer_width = "64")] {
const __ARCH_SIGEV_PREAMBLE_SIZE: usize = 4 * 2 + 8;
} else {
const __ARCH_SIGEV_PREAMBLE_SIZE: usize = 4 * 2 + 4;
}
}
const SIGEV_PAD_SIZE: usize = (SIGEV_MAX_SIZE - __ARCH_SIGEV_PREAMBLE_SIZE) / 4;

pub const PROT_NONE: ::c_int = 0;
pub const PROT_READ: ::c_int = 1;
pub const PROT_WRITE: ::c_int = 2;
Expand Down

0 comments on commit 0808995

Please sign in to comment.