Skip to content

Commit 6de7d63

Browse files
asomersJohnTitor
authored andcommitted
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 bdc4282 commit 6de7d63

File tree

4 files changed

+77
-87
lines changed

4 files changed

+77
-87
lines changed

libc-test/build.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2543,6 +2543,9 @@ fn test_freebsd(target: &str) {
25432543
// not available until FreeBSD 12, and is an anonymous union there.
25442544
("xucred", "cr_pid__c_anonymous_union") => true,
25452545

2546+
// Anonymous union
2547+
("sigevent", "_sigev_un") => true,
2548+
25462549
// m_owner field is a volatile __lwpid_t
25472550
("umutex", "m_owner") => true,
25482551
// c_has_waiters field is a volatile int32_t
@@ -4281,8 +4284,8 @@ fn test_linux(target: &str) {
42814284
(musl && struct_ == "glob_t" && field == "gl_flags") ||
42824285
// musl seems to define this as an *anonymous* bitfield
42834286
(musl && struct_ == "statvfs" && field == "__f_unused") ||
4284-
// sigev_notify_thread_id is actually part of a sigev_un union
4285-
(struct_ == "sigevent" && field == "sigev_notify_thread_id") ||
4287+
// _sigev_un is an anonymous union
4288+
(struct_ == "sigevent" && field == "_sigev_un") ||
42864289
// signalfd had SIGSYS fields added in Linux 4.18, but no libc release
42874290
// has them yet.
42884291
(struct_ == "signalfd_siginfo" && (field == "ssi_addr_lsb" ||

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

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -237,20 +237,9 @@ impl ::Clone for devstat_select_mode {
237237
}
238238

239239
s! {
240-
pub struct aiocb {
241-
pub aio_fildes: ::c_int,
242-
pub aio_offset: ::off_t,
243-
pub aio_buf: *mut ::c_void,
244-
pub aio_nbytes: ::size_t,
245-
__unused1: [::c_int; 2],
246-
__unused2: *mut ::c_void,
247-
pub aio_lio_opcode: ::c_int,
248-
pub aio_reqprio: ::c_int,
249-
// unused 3 through 5 are the __aiocb_private structure
250-
__unused3: ::c_long,
251-
__unused4: ::c_long,
252-
__unused5: *mut ::c_void,
253-
pub aio_sigevent: sigevent
240+
pub struct __c_anonymous_sigev_thread {
241+
pub _function: *mut ::c_void, // Actually a function pointer
242+
pub _attribute: *mut ::pthread_attr_t,
254243
}
255244

256245
pub struct jail {
@@ -1345,6 +1334,32 @@ s! {
13451334
}
13461335

13471336
s_no_extra_traits! {
1337+
#[cfg_attr(feature = "extra_traits", derive(Debug))]
1338+
pub struct aiocb {
1339+
pub aio_fildes: ::c_int,
1340+
pub aio_offset: ::off_t,
1341+
pub aio_buf: *mut ::c_void,
1342+
pub aio_nbytes: ::size_t,
1343+
__unused1: [::c_int; 2],
1344+
__unused2: *mut ::c_void,
1345+
pub aio_lio_opcode: ::c_int,
1346+
pub aio_reqprio: ::c_int,
1347+
// unused 3 through 5 are the __aiocb_private structure
1348+
__unused3: ::c_long,
1349+
__unused4: ::c_long,
1350+
__unused5: *mut ::c_void,
1351+
pub aio_sigevent: sigevent
1352+
}
1353+
1354+
// Can't correctly impl Debug for unions
1355+
#[allow(missing_debug_implementations)]
1356+
pub union __c_anonymous_sigev_un {
1357+
pub _threadid: ::__lwpid_t,
1358+
pub _sigev_thread: __c_anonymous_sigev_thread,
1359+
pub _kevent_flags: ::c_ushort,
1360+
__spare__: [::c_long; 8],
1361+
}
1362+
13481363
pub struct utmpx {
13491364
pub ut_type: ::c_short,
13501365
pub ut_tv: ::timeval,
@@ -1392,12 +1407,7 @@ s_no_extra_traits! {
13921407
pub sigev_notify: ::c_int,
13931408
pub sigev_signo: ::c_int,
13941409
pub sigev_value: ::sigval,
1395-
//The rest of the structure is actually a union. We expose only
1396-
//sigev_notify_thread_id because it's the most useful union member.
1397-
pub sigev_notify_thread_id: ::lwpid_t,
1398-
#[cfg(target_pointer_width = "64")]
1399-
__unused1: ::c_int,
1400-
__unused2: [::c_long; 7]
1410+
pub _sigev_un: __c_anonymous_sigev_un,
14011411
}
14021412

14031413
pub struct ptsstat {
@@ -1791,35 +1801,17 @@ cfg_if! {
17911801
}
17921802
}
17931803

1794-
impl PartialEq for sigevent {
1795-
fn eq(&self, other: &sigevent) -> bool {
1796-
self.sigev_notify == other.sigev_notify
1797-
&& self.sigev_signo == other.sigev_signo
1798-
&& self.sigev_value == other.sigev_value
1799-
&& self.sigev_notify_thread_id
1800-
== other.sigev_notify_thread_id
1801-
}
1802-
}
1803-
impl Eq for sigevent {}
18041804
impl ::fmt::Debug for sigevent {
18051805
fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
18061806
f.debug_struct("sigevent")
18071807
.field("sigev_notify", &self.sigev_notify)
18081808
.field("sigev_signo", &self.sigev_signo)
18091809
.field("sigev_value", &self.sigev_value)
1810-
.field("sigev_notify_thread_id",
1811-
&self.sigev_notify_thread_id)
1810+
// Skip _sigev_un, since we can't guarantee that it will be
1811+
// properly initialized.
18121812
.finish()
18131813
}
18141814
}
1815-
impl ::hash::Hash for sigevent {
1816-
fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
1817-
self.sigev_notify.hash(state);
1818-
self.sigev_signo.hash(state);
1819-
self.sigev_value.hash(state);
1820-
self.sigev_notify_thread_id.hash(state);
1821-
}
1822-
}
18231815

18241816
impl PartialEq for ptsstat {
18251817
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
@@ -49,24 +49,6 @@ s! {
4949
pub __statx_timestamp_pad1: [i32; 1],
5050
}
5151

52-
pub struct aiocb {
53-
pub aio_fildes: ::c_int,
54-
pub aio_lio_opcode: ::c_int,
55-
pub aio_reqprio: ::c_int,
56-
pub aio_buf: *mut ::c_void,
57-
pub aio_nbytes: ::size_t,
58-
pub aio_sigevent: ::sigevent,
59-
__next_prio: *mut aiocb,
60-
__abs_prio: ::c_int,
61-
__policy: ::c_int,
62-
__error_code: ::c_int,
63-
__return_value: ::ssize_t,
64-
pub aio_offset: off_t,
65-
#[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))]
66-
__unused1: [::c_char; 4],
67-
__glibc_reserved: [::c_char; 32]
68-
}
69-
7052
pub struct __exit_status {
7153
pub e_termination: ::c_short,
7254
pub e_exit: ::c_short,
@@ -481,6 +463,27 @@ impl siginfo_t {
481463
}
482464
}
483465

466+
s_no_extra_traits! {
467+
#[cfg_attr(feature = "extra_traits", derive(Debug))]
468+
pub struct aiocb {
469+
pub aio_fildes: ::c_int,
470+
pub aio_lio_opcode: ::c_int,
471+
pub aio_reqprio: ::c_int,
472+
pub aio_buf: *mut ::c_void,
473+
pub aio_nbytes: ::size_t,
474+
pub aio_sigevent: ::sigevent,
475+
__next_prio: *mut aiocb,
476+
__abs_prio: ::c_int,
477+
__policy: ::c_int,
478+
__error_code: ::c_int,
479+
__return_value: ::ssize_t,
480+
pub aio_offset: off_t,
481+
#[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "32"))]
482+
__unused1: [::c_char; 4],
483+
__glibc_reserved: [::c_char; 32]
484+
}
485+
}
486+
484487
// Internal, for casts to access union fields
485488
#[repr(C)]
486489
struct sifields_sigchld {

src/unix/linux_like/mod.rs

Lines changed: 19 additions & 27 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
}
@@ -220,6 +225,17 @@ s_no_extra_traits! {
220225
pub u64: u64,
221226
}
222227

228+
// Can't correctly impl Debug for unions
229+
#[allow(missing_debug_implementations)]
230+
pub union __c_anonymous_sigev_un {
231+
#[cfg(target_pointer_width = "64")]
232+
_pad: [::c_int; (64 - 2 * 4 - 8) / 4],
233+
#[cfg(target_pointer_width = "32")]
234+
_pad: [::c_int; (64 - 2 * 4 - 4) / 4],
235+
pub _tid: ::c_int,
236+
pub _sigev_thread: __c_anonymous_sigev_thread,
237+
}
238+
223239
pub struct sockaddr_un {
224240
pub sun_family: sa_family_t,
225241
pub sun_path: [::c_char; 108]
@@ -247,13 +263,7 @@ s_no_extra_traits! {
247263
pub sigev_value: ::sigval,
248264
pub sigev_signo: ::c_int,
249265
pub sigev_notify: ::c_int,
250-
// Actually a union. We only expose sigev_notify_thread_id because it's
251-
// the most useful member
252-
pub sigev_notify_thread_id: ::c_int,
253-
#[cfg(target_pointer_width = "64")]
254-
__unused1: [::c_int; 11],
255-
#[cfg(target_pointer_width = "32")]
256-
__unused1: [::c_int; 12]
266+
pub _sigev_un: __c_anonymous_sigev_un,
257267
}
258268
}
259269

@@ -401,35 +411,17 @@ cfg_if! {
401411
}
402412
}
403413

404-
impl PartialEq for sigevent {
405-
fn eq(&self, other: &sigevent) -> bool {
406-
self.sigev_value == other.sigev_value
407-
&& self.sigev_signo == other.sigev_signo
408-
&& self.sigev_notify == other.sigev_notify
409-
&& self.sigev_notify_thread_id
410-
== other.sigev_notify_thread_id
411-
}
412-
}
413-
impl Eq for sigevent {}
414414
impl ::fmt::Debug for sigevent {
415415
fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
416416
f.debug_struct("sigevent")
417417
.field("sigev_value", &self.sigev_value)
418418
.field("sigev_signo", &self.sigev_signo)
419419
.field("sigev_notify", &self.sigev_notify)
420-
.field("sigev_notify_thread_id",
421-
&self.sigev_notify_thread_id)
420+
// Skip _sigev_un, since we can't guarantee that it will be
421+
// properly initialized.
422422
.finish()
423423
}
424424
}
425-
impl ::hash::Hash for sigevent {
426-
fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
427-
self.sigev_value.hash(state);
428-
self.sigev_signo.hash(state);
429-
self.sigev_notify.hash(state);
430-
self.sigev_notify_thread_id.hash(state);
431-
}
432-
}
433425
}
434426
}
435427

0 commit comments

Comments
 (0)