@@ -1096,12 +1096,137 @@ mod sigevent {
10961096 use std:: mem;
10971097 use super :: SigevNotify ;
10981098
1099+ #[ cfg( target_os = "freebsd" ) ]
1100+ pub ( crate ) use ffi:: sigevent as libc_sigevent;
1101+ #[ cfg( not( target_os = "freebsd" ) ) ]
1102+ pub ( crate ) use libc:: sigevent as libc_sigevent;
1103+
1104+ // For FreeBSD only, we define the C structure here. Because the structure
1105+ // defined in libc isn't correct. The real sigevent contains union fields,
1106+ // but libc could not represent those when sigevent was originally added, so
1107+ // instead libc simply defined the most useful field. Now that Rust can
1108+ // represent unions, there's a PR to libc to fix it. However, it's stuck
1109+ // forever due to backwards compatibility concerns. Even though there's a
1110+ // workaround, libc refuses to merge it. I think it's just too complicated
1111+ // for them to want to think about right now, because that project is
1112+ // short-staffed. So we define it here instead, so we won't have to wait on
1113+ // libc.
1114+ // https://github.com/rust-lang/libc/pull/2813
1115+ #[ cfg( target_os = "freebsd" ) ]
1116+ mod ffi {
1117+ use std:: { fmt, hash} ;
1118+
1119+ #[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq ) ]
1120+ #[ repr( C ) ]
1121+ pub struct __c_anonymous_sigev_thread {
1122+ pub _function: * mut libc:: c_void, // Actually a function pointer
1123+ pub _attribute: * mut libc:: pthread_attr_t,
1124+ }
1125+ #[ derive( Clone , Copy ) ]
1126+ // This will never be used on its own, and its parent has a Debug impl,
1127+ // so it doesn't need one.
1128+ #[ allow( missing_debug_implementations) ]
1129+ #[ repr( C ) ]
1130+ pub union __c_anonymous_sigev_un {
1131+ pub _threadid: libc:: __lwpid_t,
1132+ pub _sigev_thread: __c_anonymous_sigev_thread,
1133+ pub _kevent_flags: libc:: c_ushort,
1134+ __spare__: [ libc:: c_long; 8 ] ,
1135+ }
1136+
1137+ #[ derive( Clone , Copy ) ]
1138+ #[ repr( C ) ]
1139+ pub struct sigevent {
1140+ pub sigev_notify: libc:: c_int,
1141+ pub sigev_signo: libc:: c_int,
1142+ pub sigev_value: libc:: sigval,
1143+ pub _sigev_un: __c_anonymous_sigev_un,
1144+ }
1145+
1146+ impl fmt:: Debug for sigevent {
1147+ fn fmt( & self , f: & mut fmt:: Formatter ) -> fmt:: Result {
1148+ let mut ds = f. debug_struct( "sigevent" ) ;
1149+ ds. field( "sigev_notify" , & self . sigev_notify)
1150+ . field( "sigev_signo" , & self . sigev_signo)
1151+ . field( "sigev_value" , & self . sigev_value) ;
1152+ // Safe because we check the sigev_notify discriminant
1153+ unsafe {
1154+ match self . sigev_notify {
1155+ libc:: SIGEV_KEVENT => {
1156+ ds. field( "sigev_notify_kevent_flags" , & self . _sigev_un. _kevent_flags) ;
1157+ }
1158+ libc:: SIGEV_THREAD_ID => {
1159+ ds. field( "sigev_notify_thread_id" , & self . _sigev_un. _threadid) ;
1160+ }
1161+ libc:: SIGEV_THREAD => {
1162+ ds. field( "sigev_notify_function" , & self . _sigev_un. _sigev_thread. _function) ;
1163+ ds. field( "sigev_notify_attributes" , & self . _sigev_un. _sigev_thread. _attribute) ;
1164+ }
1165+ _ => ( )
1166+ } ;
1167+ }
1168+ ds. finish( )
1169+ }
1170+ }
1171+
1172+ impl PartialEq for sigevent {
1173+ fn eq( & self , other: & Self ) -> bool {
1174+ let mut equals = self . sigev_notify == other. sigev_notify;
1175+ equals &= self . sigev_signo == other. sigev_signo;
1176+ equals &= self . sigev_value == other. sigev_value;
1177+ // Safe because we check the sigev_notify discriminant
1178+ unsafe {
1179+ match self . sigev_notify {
1180+ libc:: SIGEV_KEVENT => {
1181+ equals &= self . _sigev_un. _kevent_flags == other. _sigev_un. _kevent_flags;
1182+ }
1183+ libc:: SIGEV_THREAD_ID => {
1184+ equals &= self . _sigev_un. _threadid == other. _sigev_un. _threadid;
1185+ }
1186+ libc:: SIGEV_THREAD => {
1187+ equals &= self . _sigev_un. _sigev_thread == other. _sigev_un. _sigev_thread;
1188+ }
1189+ _ => /* The union field is don't care */ ( )
1190+ }
1191+ }
1192+ equals
1193+ }
1194+ }
1195+
1196+ impl Eq for sigevent { }
1197+
1198+ impl hash:: Hash for sigevent {
1199+ fn hash<H : hash:: Hasher >( & self , s: & mut H ) {
1200+ self . sigev_notify. hash( s) ;
1201+ self . sigev_signo. hash( s) ;
1202+ self . sigev_value. hash( s) ;
1203+ // Safe because we check the sigev_notify discriminant
1204+ unsafe {
1205+ match self . sigev_notify {
1206+ libc:: SIGEV_KEVENT => {
1207+ self . _sigev_un. _kevent_flags. hash( s) ;
1208+ }
1209+ libc:: SIGEV_THREAD_ID => {
1210+ self . _sigev_un. _threadid. hash( s) ;
1211+ }
1212+ libc:: SIGEV_THREAD => {
1213+ self . _sigev_un. _sigev_thread. hash( s) ;
1214+ }
1215+ _ => /* The union field is don't care */ ( )
1216+ }
1217+ }
1218+ }
1219+ }
1220+ }
1221+
10991222 /// Used to request asynchronous notification of the completion of certain
11001223 /// events, such as POSIX AIO and timers.
11011224 #[ repr( C ) ]
1102- #[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq ) ]
1225+ #[ derive( Clone , Debug , Eq , Hash , PartialEq ) ]
1226+ // It can't be Copy on all platforms.
1227+ #[ allow( missing_copy_implementations) ]
11031228 pub struct SigEvent {
1104- sigevent: libc :: sigevent
1229+ sigevent: libc_sigevent
11051230 }
11061231
11071232 impl SigEvent {
@@ -1119,7 +1244,7 @@ mod sigevent {
11191244 /// `SIGEV_SIGNAL`. That field is part of a union that shares space with the
11201245 /// more genuinely useful `sigev_notify_thread_id`
11211246 pub fn new( sigev_notify: SigevNotify ) -> SigEvent {
1122- let mut sev: libc :: sigevent = unsafe { mem:: zeroed( ) } ;
1247+ let mut sev: libc_sigevent = unsafe { mem:: zeroed( ) } ;
11231248 match sigev_notify {
11241249 SigevNotify :: SigevNone => {
11251250 sev. sigev_notify = libc:: SIGEV_NONE ;
@@ -1155,24 +1280,54 @@ mod sigevent {
11551280 sev. sigev_notify = libc:: SIGEV_THREAD_ID ;
11561281 sev. sigev_signo = signal as libc:: c_int;
11571282 sev. sigev_value. sival_ptr = si_value as * mut libc:: c_void;
1158- sev. _sigev_un . _tid = thread_id;
1283+ sev. sigev_notify_thread_id = thread_id;
11591284 }
11601285 }
11611286 SigEvent { sigevent: sev}
11621287 }
11631288
11641289 /// Return a copy of the inner structure
1290+ #[ cfg( target_os = "freebsd" ) ]
1291+ pub fn sigevent( & self ) -> libc:: sigevent {
1292+ // Safe because they're really the same structure. See
1293+ // https://github.com/rust-lang/libc/pull/2813
1294+ unsafe {
1295+ mem:: transmute:: <libc_sigevent, libc:: sigevent>( self . sigevent)
1296+ }
1297+ }
1298+
1299+ /// Return a copy of the inner structure
1300+ #[ cfg( not( target_os = "freebsd" ) ) ]
11651301 pub fn sigevent( & self ) -> libc:: sigevent {
11661302 self . sigevent
11671303 }
11681304
11691305 /// Returns a mutable pointer to the `sigevent` wrapped by `self`
1306+ #[ cfg( target_os = "freebsd" ) ]
1307+ pub fn as_mut_ptr( & mut self ) -> * mut libc:: sigevent {
1308+ // Safe because they're really the same structure. See
1309+ // https://github.com/rust-lang/libc/pull/2813
1310+ & mut self . sigevent as * mut libc_sigevent as * mut libc:: sigevent
1311+ }
1312+
1313+ /// Returns a mutable pointer to the `sigevent` wrapped by `self`
1314+ #[ cfg( not( target_os = "freebsd" ) ) ]
11701315 pub fn as_mut_ptr( & mut self ) -> * mut libc:: sigevent {
11711316 & mut self . sigevent
11721317 }
11731318 }
11741319
11751320 impl <' a> From <& ' a libc:: sigevent> for SigEvent {
1321+ #[ cfg( target_os = "freebsd" ) ]
1322+ fn from( sigevent: & libc:: sigevent) -> Self {
1323+ // Safe because they're really the same structure. See
1324+ // https://github.com/rust-lang/libc/pull/2813
1325+ let sigevent = unsafe {
1326+ mem:: transmute:: <libc:: sigevent, libc_sigevent>( * sigevent)
1327+ } ;
1328+ SigEvent { sigevent }
1329+ }
1330+ #[ cfg( not( target_os = "freebsd" ) ) ]
11761331 fn from( sigevent: & libc:: sigevent) -> Self {
11771332 SigEvent { sigevent: * sigevent }
11781333 }
0 commit comments