Skip to content

Commit e3b96ef

Browse files
committed
Fix the definition of sigevent on FreeBSD and Linux
It was originally defined back before rust could represent C unions. So instead of defining the union field correctly, it simply defined that union's most useful field. Define it correctly now. Remove traits that can't be safely implemented on a union: PartialEq, Eq, and Hash. Define Debug, but exclude the union field.
1 parent ca3a399 commit e3b96ef

File tree

5 files changed

+106
-103
lines changed

5 files changed

+106
-103
lines changed

libc-test/build.rs

Lines changed: 13 additions & 2 deletions
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,
@@ -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

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -236,20 +236,9 @@ 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: *mut ::c_void, // Actually a function pointer
241+
pub _attribute: *mut ::pthread_attr_t,
253242
}
254243

255244
pub struct jail {
@@ -1351,6 +1340,32 @@ s! {
13511340
}
13521341

13531342
s_no_extra_traits! {
1343+
#[cfg_attr(feature = "extra_traits", derive(Debug))]
1344+
pub struct aiocb {
1345+
pub aio_fildes: ::c_int,
1346+
pub aio_offset: ::off_t,
1347+
pub aio_buf: *mut ::c_void,
1348+
pub aio_nbytes: ::size_t,
1349+
__unused1: [::c_int; 2],
1350+
__unused2: *mut ::c_void,
1351+
pub aio_lio_opcode: ::c_int,
1352+
pub aio_reqprio: ::c_int,
1353+
// unused 3 through 5 are the __aiocb_private structure
1354+
__unused3: ::c_long,
1355+
__unused4: ::c_long,
1356+
__unused5: *mut ::c_void,
1357+
pub aio_sigevent: sigevent,
1358+
}
1359+
1360+
// Can't correctly impl Debug for unions
1361+
#[allow(missing_debug_implementations)]
1362+
pub union __c_anonymous_sigev_un {
1363+
pub _threadid: ::__lwpid_t,
1364+
pub _sigev_thread: __c_anonymous_sigev_thread,
1365+
pub _kevent_flags: ::c_ushort,
1366+
__spare__: [::c_long; 8],
1367+
}
1368+
13541369
pub struct utmpx {
13551370
pub ut_type: ::c_short,
13561371
pub ut_tv: ::timeval,
@@ -1398,12 +1413,7 @@ s_no_extra_traits! {
13981413
pub sigev_notify: ::c_int,
13991414
pub sigev_signo: ::c_int,
14001415
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],
1416+
pub _sigev_un: __c_anonymous_sigev_un,
14071417
}
14081418

14091419
pub struct ptsstat {
@@ -1819,33 +1829,17 @@ cfg_if! {
18191829
}
18201830
}
18211831

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 {}
18311832
impl ::fmt::Debug for sigevent {
18321833
fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
18331834
f.debug_struct("sigevent")
18341835
.field("sigev_notify", &self.sigev_notify)
18351836
.field("sigev_signo", &self.sigev_signo)
18361837
.field("sigev_value", &self.sigev_value)
1837-
.field("sigev_notify_thread_id", &self.sigev_notify_thread_id)
1838+
// Skip _sigev_un, since we can't guarantee that it will be
1839+
// properly initialized.
18381840
.finish()
18391841
}
18401842
}
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-
}
18491843

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

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

Lines changed: 21 additions & 18 deletions
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,27 @@ 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+
pub aio_offset: off_t,
510+
#[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))]
511+
__unused1: [::c_char; 4],
512+
__glibc_reserved: [::c_char; 32],
513+
}
514+
}
515+
513516
// Internal, for casts to access union fields
514517
#[repr(C)]
515518
struct sifields_sigchld {

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

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -117,26 +117,6 @@ impl siginfo_t {
117117
}
118118

119119
s! {
120-
pub struct aiocb {
121-
pub aio_fildes: ::c_int,
122-
pub aio_lio_opcode: ::c_int,
123-
pub aio_reqprio: ::c_int,
124-
pub aio_buf: *mut ::c_void,
125-
pub aio_nbytes: ::size_t,
126-
pub aio_sigevent: ::sigevent,
127-
__td: *mut ::c_void,
128-
__lock: [::c_int; 2],
129-
__err: ::c_int,
130-
__ret: ::ssize_t,
131-
pub aio_offset: off_t,
132-
__next: *mut ::c_void,
133-
__prev: *mut ::c_void,
134-
#[cfg(target_pointer_width = "32")]
135-
__dummy4: [::c_char; 24],
136-
#[cfg(target_pointer_width = "64")]
137-
__dummy4: [::c_char; 16],
138-
}
139-
140120
pub struct sigaction {
141121
pub sa_sigaction: ::sighandler_t,
142122
pub sa_mask: ::sigset_t,
@@ -419,6 +399,27 @@ s! {
419399
}
420400

421401
s_no_extra_traits! {
402+
#[cfg_attr(feature = "extra_traits", derive(Debug))]
403+
pub struct aiocb {
404+
pub aio_fildes: ::c_int,
405+
pub aio_lio_opcode: ::c_int,
406+
pub aio_reqprio: ::c_int,
407+
pub aio_buf: *mut ::c_void,
408+
pub aio_nbytes: ::size_t,
409+
pub aio_sigevent: ::sigevent,
410+
__td: *mut ::c_void,
411+
__lock: [::c_int; 2],
412+
__err: ::c_int,
413+
__ret: ::ssize_t,
414+
pub aio_offset: off_t,
415+
__next: *mut ::c_void,
416+
__prev: *mut ::c_void,
417+
#[cfg(target_pointer_width = "32")]
418+
__dummy4: [::c_char; 24],
419+
#[cfg(target_pointer_width = "64")]
420+
__dummy4: [::c_char; 16],
421+
}
422+
422423
pub struct sysinfo {
423424
pub uptime: ::c_ulong,
424425
pub loads: [::c_ulong; 3],

src/unix/linux_like/mod.rs

Lines changed: 19 additions & 25 deletions
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: *mut ::c_void, // Actually a function pointer
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,17 @@ 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+
#[cfg(target_pointer_width = "64")]
273+
_pad: [::c_int; (64 - 2 * 4 - 8) / 4],
274+
#[cfg(target_pointer_width = "32")]
275+
_pad: [::c_int; (64 - 2 * 4 - 4) / 4],
276+
pub _tid: ::c_int,
277+
pub _sigev_thread: __c_anonymous_sigev_thread,
278+
}
279+
264280
pub struct sockaddr_un {
265281
pub sun_family: sa_family_t,
266282
pub sun_path: [::c_char; 108],
@@ -288,13 +304,7 @@ s_no_extra_traits! {
288304
pub sigev_value: ::sigval,
289305
pub sigev_signo: ::c_int,
290306
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],
307+
pub _sigev_un: __c_anonymous_sigev_un,
298308
}
299309
}
300310

@@ -441,33 +451,17 @@ cfg_if! {
441451
}
442452
}
443453

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 {}
453454
impl ::fmt::Debug for sigevent {
454455
fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
455456
f.debug_struct("sigevent")
456457
.field("sigev_value", &self.sigev_value)
457458
.field("sigev_signo", &self.sigev_signo)
458459
.field("sigev_notify", &self.sigev_notify)
459-
.field("sigev_notify_thread_id", &self.sigev_notify_thread_id)
460+
// Skip _sigev_un, since we can't guarantee that it will be
461+
// properly initialized.
460462
.finish()
461463
}
462464
}
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-
}
471465
}
472466
}
473467

0 commit comments

Comments
 (0)