Skip to content

Commit 0808995

Browse files
authored
Merge pull request #3630 from asomers/sigevent2
Fix the definition of sigevent on FreeBSD and Linux
2 parents 951cab5 + d255379 commit 0808995

File tree

5 files changed

+121
-104
lines changed

5 files changed

+121
-104
lines changed

libc-test/build.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -2080,6 +2080,9 @@ fn test_android(target: &str) {
20802080
("Elf32_Phdr", "p_type") => true,
20812081
("Elf64_Phdr", "p_type") => true,
20822082

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

2697+
// Anonymous union
2698+
("sigevent", "_sigev_un") => true,
2699+
26942700
// m_owner field is a volatile __lwpid_t
26952701
("umutex", "m_owner") => true,
26962702
// c_has_waiters field is a volatile int32_t
@@ -2883,6 +2889,9 @@ fn test_emscripten(target: &str) {
28832889
});
28842890

28852891
cfg.skip_struct(move |ty| {
2892+
if ty.starts_with("__c_anonymous_") {
2893+
return true;
2894+
}
28862895
match ty {
28872896
// This is actually a union, not a struct
28882897
"sigval" => true,
@@ -2968,6 +2977,8 @@ fn test_emscripten(target: &str) {
29682977
});
29692978

29702979
cfg.skip_field(move |struct_, field| {
2980+
// _sigev_un is an anonymous union
2981+
(struct_ == "sigevent" && field == "_sigev_un") ||
29712982
// this is actually a union on linux, so we can't represent it well and
29722983
// just insert some padding.
29732984
(struct_ == "siginfo_t" && field == "_pad") ||
@@ -4359,8 +4370,8 @@ fn test_linux(target: &str) {
43594370
(musl && struct_ == "glob_t" && field == "gl_flags") ||
43604371
// musl seems to define this as an *anonymous* bitfield
43614372
(musl && struct_ == "statvfs" && field == "__f_unused") ||
4362-
// sigev_notify_thread_id is actually part of a sigev_un union
4363-
(struct_ == "sigevent" && field == "sigev_notify_thread_id") ||
4373+
// _sigev_un is an anonymous union
4374+
(struct_ == "sigevent" && field == "_sigev_un") ||
43644375
// signalfd had SIGSYS fields added in Linux 4.18, but no libc release
43654376
// has them yet.
43664377
(struct_ == "signalfd_siginfo" && (field == "ssi_addr_lsb" ||

src/unix/bsd/freebsdlike/freebsd/mod.rs

+37-38
Original file line numberDiff line numberDiff line change
@@ -236,20 +236,10 @@ impl ::Clone for devstat_select_mode {
236236
}
237237

238238
s! {
239-
pub struct aiocb {
240-
pub aio_fildes: ::c_int,
241-
pub aio_offset: ::off_t,
242-
pub aio_buf: *mut ::c_void,
243-
pub aio_nbytes: ::size_t,
244-
__unused1: [::c_int; 2],
245-
__unused2: *mut ::c_void,
246-
pub aio_lio_opcode: ::c_int,
247-
pub aio_reqprio: ::c_int,
248-
// unused 3 through 5 are the __aiocb_private structure
249-
__unused3: ::c_long,
250-
__unused4: ::c_long,
251-
__unused5: *mut ::c_void,
252-
pub aio_sigevent: sigevent,
239+
pub struct __c_anonymous_sigev_thread {
240+
pub _function: Option<extern "C" fn(::sigval) -> *mut ::c_void>,
241+
//pub _function: *mut ::c_void, // Actually a function pointer
242+
pub _attribute: *mut ::pthread_attr_t,
253243
}
254244

255245
pub struct jail {
@@ -1351,6 +1341,36 @@ s! {
13511341
}
13521342

13531343
s_no_extra_traits! {
1344+
#[cfg_attr(feature = "extra_traits", derive(Debug))]
1345+
pub struct __aiocb_private {
1346+
status: ::c_long,
1347+
error: ::c_long,
1348+
spare: *mut ::c_void,
1349+
}
1350+
1351+
#[cfg_attr(feature = "extra_traits", derive(Debug))]
1352+
pub struct aiocb {
1353+
pub aio_fildes: ::c_int,
1354+
pub aio_offset: ::off_t,
1355+
pub aio_buf: *mut ::c_void,
1356+
pub aio_nbytes: ::size_t,
1357+
__spare__: [::c_int; 2],
1358+
__spare2__: *mut ::c_void,
1359+
pub aio_lio_opcode: ::c_int,
1360+
pub aio_reqprio: ::c_int,
1361+
_aiocb_private: __aiocb_private,
1362+
pub aio_sigevent: sigevent,
1363+
}
1364+
1365+
// Can't correctly impl Debug for unions
1366+
#[allow(missing_debug_implementations)]
1367+
pub union __c_anonymous_sigev_un {
1368+
pub _threadid: ::__lwpid_t,
1369+
pub _sigev_thread: __c_anonymous_sigev_thread,
1370+
pub _kevent_flags: ::c_ushort,
1371+
__spare__: [::c_long; 8],
1372+
}
1373+
13541374
pub struct utmpx {
13551375
pub ut_type: ::c_short,
13561376
pub ut_tv: ::timeval,
@@ -1398,12 +1418,7 @@ s_no_extra_traits! {
13981418
pub sigev_notify: ::c_int,
13991419
pub sigev_signo: ::c_int,
14001420
pub sigev_value: ::sigval,
1401-
//The rest of the structure is actually a union. We expose only
1402-
//sigev_notify_thread_id because it's the most useful union member.
1403-
pub sigev_notify_thread_id: ::lwpid_t,
1404-
#[cfg(target_pointer_width = "64")]
1405-
__unused1: ::c_int,
1406-
__unused2: [::c_long; 7],
1421+
pub _sigev_un: __c_anonymous_sigev_un,
14071422
}
14081423

14091424
pub struct ptsstat {
@@ -1819,33 +1834,17 @@ cfg_if! {
18191834
}
18201835
}
18211836

1822-
impl PartialEq for sigevent {
1823-
fn eq(&self, other: &sigevent) -> bool {
1824-
self.sigev_notify == other.sigev_notify
1825-
&& self.sigev_signo == other.sigev_signo
1826-
&& self.sigev_value == other.sigev_value
1827-
&& self.sigev_notify_thread_id == other.sigev_notify_thread_id
1828-
}
1829-
}
1830-
impl Eq for sigevent {}
18311837
impl ::fmt::Debug for sigevent {
18321838
fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
18331839
f.debug_struct("sigevent")
18341840
.field("sigev_notify", &self.sigev_notify)
18351841
.field("sigev_signo", &self.sigev_signo)
18361842
.field("sigev_value", &self.sigev_value)
1837-
.field("sigev_notify_thread_id", &self.sigev_notify_thread_id)
1843+
// Skip _sigev_un, since we can't guarantee that it will be
1844+
// properly initialized.
18381845
.finish()
18391846
}
18401847
}
1841-
impl ::hash::Hash for sigevent {
1842-
fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
1843-
self.sigev_notify.hash(state);
1844-
self.sigev_signo.hash(state);
1845-
self.sigev_value.hash(state);
1846-
self.sigev_notify_thread_id.hash(state);
1847-
}
1848-
}
18491848

18501849
impl PartialEq for ptsstat {
18511850
fn eq(&self, other: &ptsstat) -> bool {

src/unix/linux_like/linux/gnu/mod.rs

+22-18
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,6 @@ cfg_if! {
1616
}
1717

1818
s! {
19-
pub struct aiocb {
20-
pub aio_fildes: ::c_int,
21-
pub aio_lio_opcode: ::c_int,
22-
pub aio_reqprio: ::c_int,
23-
pub aio_buf: *mut ::c_void,
24-
pub aio_nbytes: ::size_t,
25-
pub aio_sigevent: ::sigevent,
26-
__next_prio: *mut aiocb,
27-
__abs_prio: ::c_int,
28-
__policy: ::c_int,
29-
__error_code: ::c_int,
30-
__return_value: ::ssize_t,
31-
pub aio_offset: off_t,
32-
#[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))]
33-
__unused1: [::c_char; 4],
34-
__glibc_reserved: [::c_char; 32],
35-
}
36-
3719
pub struct __exit_status {
3820
pub e_termination: ::c_short,
3921
pub e_exit: ::c_short,
@@ -510,6 +492,28 @@ impl siginfo_t {
510492
}
511493
}
512494

495+
s_no_extra_traits! {
496+
#[cfg_attr(feature = "extra_traits", derive(Debug))]
497+
pub struct aiocb {
498+
pub aio_fildes: ::c_int,
499+
pub aio_lio_opcode: ::c_int,
500+
pub aio_reqprio: ::c_int,
501+
pub aio_buf: *mut ::c_void,
502+
pub aio_nbytes: ::size_t,
503+
pub aio_sigevent: ::sigevent,
504+
__next_prio: *mut aiocb,
505+
__abs_prio: ::c_int,
506+
__policy: ::c_int,
507+
__error_code: ::c_int,
508+
__return_value: ::ssize_t,
509+
// FIXME(off64): visible fields depend on __USE_FILE_OFFSET64
510+
pub aio_offset: off_t,
511+
#[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))]
512+
__pad: [::c_char; 4],
513+
__glibc_reserved: [::c_char; 32],
514+
}
515+
}
516+
513517
// Internal, for casts to access union fields
514518
#[repr(C)]
515519
struct sifields_sigchld {

src/unix/linux_like/linux/musl/mod.rs

+22-20
Original file line numberDiff line numberDiff line change
@@ -119,26 +119,6 @@ impl siginfo_t {
119119
}
120120

121121
s! {
122-
pub struct aiocb {
123-
pub aio_fildes: ::c_int,
124-
pub aio_lio_opcode: ::c_int,
125-
pub aio_reqprio: ::c_int,
126-
pub aio_buf: *mut ::c_void,
127-
pub aio_nbytes: ::size_t,
128-
pub aio_sigevent: ::sigevent,
129-
__td: *mut ::c_void,
130-
__lock: [::c_int; 2],
131-
__err: ::c_int,
132-
__ret: ::ssize_t,
133-
pub aio_offset: off_t,
134-
__next: *mut ::c_void,
135-
__prev: *mut ::c_void,
136-
#[cfg(target_pointer_width = "32")]
137-
__dummy4: [::c_char; 24],
138-
#[cfg(target_pointer_width = "64")]
139-
__dummy4: [::c_char; 16],
140-
}
141-
142122
pub struct sigaction {
143123
pub sa_sigaction: ::sighandler_t,
144124
pub sa_mask: ::sigset_t,
@@ -496,6 +476,28 @@ s! {
496476
}
497477

498478
s_no_extra_traits! {
479+
#[cfg_attr(feature = "extra_traits", derive(Debug))]
480+
pub struct aiocb {
481+
pub aio_fildes: ::c_int,
482+
pub aio_lio_opcode: ::c_int,
483+
pub aio_reqprio: ::c_int,
484+
pub aio_buf: *mut ::c_void,
485+
pub aio_nbytes: ::size_t,
486+
pub aio_sigevent: ::sigevent,
487+
__td: *mut ::c_void,
488+
__lock: [::c_int; 2],
489+
__err: ::c_int,
490+
__ret: ::ssize_t,
491+
pub aio_offset: off_t,
492+
__next: *mut ::c_void,
493+
__prev: *mut ::c_void,
494+
// FIXME(ctest): length should be `32 - 2 * core::mem::size_of::<*const ()>()`
495+
#[cfg(target_pointer_width = "32")]
496+
__dummy4: [::c_char; 24],
497+
#[cfg(target_pointer_width = "64")]
498+
__dummy4: [::c_char; 16],
499+
}
500+
499501
pub struct sysinfo {
500502
pub uptime: ::c_ulong,
501503
pub loads: [::c_ulong; 3],

src/unix/linux_like/mod.rs

+26-25
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ missing! {
1212
}
1313

1414
s! {
15+
pub struct __c_anonymous_sigev_thread {
16+
pub _function: Option<extern "C" fn(::sigval) -> *mut ::c_void>,
17+
pub _attribute: *mut ::pthread_attr_t,
18+
}
19+
1520
pub struct in_addr {
1621
pub s_addr: ::in_addr_t,
1722
}
@@ -261,6 +266,14 @@ s_no_extra_traits! {
261266
pub u64: u64,
262267
}
263268

269+
// Can't correctly impl Debug for unions
270+
#[allow(missing_debug_implementations)]
271+
pub union __c_anonymous_sigev_un {
272+
_pad: [::c_int; SIGEV_PAD_SIZE],
273+
pub _tid: ::c_int,
274+
pub _sigev_thread: __c_anonymous_sigev_thread,
275+
}
276+
264277
pub struct sockaddr_un {
265278
pub sun_family: sa_family_t,
266279
pub sun_path: [::c_char; 108],
@@ -288,13 +301,7 @@ s_no_extra_traits! {
288301
pub sigev_value: ::sigval,
289302
pub sigev_signo: ::c_int,
290303
pub sigev_notify: ::c_int,
291-
// Actually a union. We only expose sigev_notify_thread_id because it's
292-
// the most useful member
293-
pub sigev_notify_thread_id: ::c_int,
294-
#[cfg(target_pointer_width = "64")]
295-
__unused1: [::c_int; 11],
296-
#[cfg(target_pointer_width = "32")]
297-
__unused1: [::c_int; 12],
304+
pub _sigev_un: __c_anonymous_sigev_un,
298305
}
299306
}
300307

@@ -441,33 +448,17 @@ cfg_if! {
441448
}
442449
}
443450

444-
impl PartialEq for sigevent {
445-
fn eq(&self, other: &sigevent) -> bool {
446-
self.sigev_value == other.sigev_value
447-
&& self.sigev_signo == other.sigev_signo
448-
&& self.sigev_notify == other.sigev_notify
449-
&& self.sigev_notify_thread_id == other.sigev_notify_thread_id
450-
}
451-
}
452-
impl Eq for sigevent {}
453451
impl ::fmt::Debug for sigevent {
454452
fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
455453
f.debug_struct("sigevent")
456454
.field("sigev_value", &self.sigev_value)
457455
.field("sigev_signo", &self.sigev_signo)
458456
.field("sigev_notify", &self.sigev_notify)
459-
.field("sigev_notify_thread_id", &self.sigev_notify_thread_id)
457+
// Skip _sigev_un, since we can't guarantee that it will be
458+
// properly initialized.
460459
.finish()
461460
}
462461
}
463-
impl ::hash::Hash for sigevent {
464-
fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
465-
self.sigev_value.hash(state);
466-
self.sigev_signo.hash(state);
467-
self.sigev_notify.hash(state);
468-
self.sigev_notify_thread_id.hash(state);
469-
}
470-
}
471462
}
472463
}
473464

@@ -582,6 +573,16 @@ pub const SIGPIPE: ::c_int = 13;
582573
pub const SIGALRM: ::c_int = 14;
583574
pub const SIGTERM: ::c_int = 15;
584575

576+
const SIGEV_MAX_SIZE: usize = 64;
577+
cfg_if! {
578+
if #[cfg(target_pointer_width = "64")] {
579+
const __ARCH_SIGEV_PREAMBLE_SIZE: usize = 4 * 2 + 8;
580+
} else {
581+
const __ARCH_SIGEV_PREAMBLE_SIZE: usize = 4 * 2 + 4;
582+
}
583+
}
584+
const SIGEV_PAD_SIZE: usize = (SIGEV_MAX_SIZE - __ARCH_SIGEV_PREAMBLE_SIZE) / 4;
585+
585586
pub const PROT_NONE: ::c_int = 0;
586587
pub const PROT_READ: ::c_int = 1;
587588
pub const PROT_WRITE: ::c_int = 2;

0 commit comments

Comments
 (0)