@@ -1096,12 +1096,137 @@ mod sigevent {
1096
1096
use std:: mem;
1097
1097
use super :: SigevNotify ;
1098
1098
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
+
1099
1222
/// Used to request asynchronous notification of the completion of certain
1100
1223
/// events, such as POSIX AIO and timers.
1101
1224
#[ 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) ]
1103
1228
pub struct SigEvent {
1104
- sigevent: libc :: sigevent
1229
+ sigevent: libc_sigevent
1105
1230
}
1106
1231
1107
1232
impl SigEvent {
@@ -1119,7 +1244,7 @@ mod sigevent {
1119
1244
/// `SIGEV_SIGNAL`. That field is part of a union that shares space with the
1120
1245
/// more genuinely useful `sigev_notify_thread_id`
1121
1246
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( ) } ;
1123
1248
match sigev_notify {
1124
1249
SigevNotify :: SigevNone => {
1125
1250
sev. sigev_notify = libc:: SIGEV_NONE ;
@@ -1155,24 +1280,54 @@ mod sigevent {
1155
1280
sev. sigev_notify = libc:: SIGEV_THREAD_ID ;
1156
1281
sev. sigev_signo = signal as libc:: c_int;
1157
1282
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;
1159
1284
}
1160
1285
}
1161
1286
SigEvent { sigevent: sev}
1162
1287
}
1163
1288
1164
1289
/// 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" ) ) ]
1165
1301
pub fn sigevent( & self ) -> libc:: sigevent {
1166
1302
self . sigevent
1167
1303
}
1168
1304
1169
1305
/// 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" ) ) ]
1170
1315
pub fn as_mut_ptr( & mut self ) -> * mut libc:: sigevent {
1171
1316
& mut self . sigevent
1172
1317
}
1173
1318
}
1174
1319
1175
1320
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" ) ) ]
1176
1331
fn from( sigevent: & libc:: sigevent) -> Self {
1177
1332
SigEvent { sigevent: * sigevent }
1178
1333
}
0 commit comments