@@ -1096,12 +1096,181 @@ 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
+ // Linter false positive: this type actually _can't_ implement Copy.
1126
+ // https://github.com/rust-lang/rust/issues/115014
1127
+ #[ allow( missing_copy_implementations) ]
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
+ #[ repr( C ) ]
1138
+ pub struct sigevent {
1139
+ pub sigev_notify: libc:: c_int,
1140
+ pub sigev_signo: libc:: c_int,
1141
+ pub sigev_value: libc:: sigval,
1142
+ pub _sigev_un: __c_anonymous_sigev_un,
1143
+ }
1144
+
1145
+ impl Clone for sigevent {
1146
+ fn clone( & self ) -> Self {
1147
+ let mut sigevent = std:: mem:: MaybeUninit :: <sigevent>:: uninit( ) ;
1148
+ // Safe because sigevent's lifetime outlives this block
1149
+ unsafe {
1150
+ ( * sigevent. as_mut_ptr( ) ) . sigev_notify = self . sigev_notify;
1151
+ ( * sigevent. as_mut_ptr( ) ) . sigev_signo = self . sigev_signo;
1152
+ ( * sigevent. as_mut_ptr( ) ) . sigev_value = self . sigev_value;
1153
+ match self . sigev_notify {
1154
+ libc:: SIGEV_KEVENT => {
1155
+ ( * sigevent. as_mut_ptr( ) ) . _sigev_un. _kevent_flags =
1156
+ self . _sigev_un. _kevent_flags;
1157
+ } ,
1158
+ libc:: SIGEV_THREAD_ID => {
1159
+ ( * sigevent. as_mut_ptr( ) ) . _sigev_un. _threadid =
1160
+ self . _sigev_un. _threadid;
1161
+ } ,
1162
+ libc:: SIGEV_THREAD => {
1163
+ ( * sigevent. as_mut_ptr( ) ) . _sigev_un. _sigev_thread =
1164
+ self . _sigev_un. _sigev_thread;
1165
+ } ,
1166
+ libc:: SIGEV_NONE | libc:: SIGEV_SIGNAL => {
1167
+ // The _sigev_un field is DON'T CARE
1168
+ }
1169
+ _ => {
1170
+ // Maybe the OS returned a sigevent of a type that
1171
+ // Nix doesn't know about. Or maybe the structure
1172
+ // is just corrupt. In either case, we'll copy the
1173
+ // entire union. This isn't UB, because we don't
1174
+ // provide a way for the user to initialize such a
1175
+ // sigevent, so the structure must've been returned
1176
+ // by the kernel, which means it's fully
1177
+ // initialized.
1178
+ ( * sigevent. as_mut_ptr( ) ) . _sigev_un. __spare__ =
1179
+ self . _sigev_un. __spare__;
1180
+ }
1181
+ }
1182
+ }
1183
+ // Safe because we initialized every field.
1184
+ unsafe {
1185
+ sigevent. assume_init( )
1186
+ }
1187
+ }
1188
+ }
1189
+
1190
+ impl fmt:: Debug for sigevent {
1191
+ fn fmt( & self , f: & mut fmt:: Formatter ) -> fmt:: Result {
1192
+ let mut ds = f. debug_struct( "sigevent" ) ;
1193
+ ds. field( "sigev_notify" , & self . sigev_notify)
1194
+ . field( "sigev_signo" , & self . sigev_signo)
1195
+ . field( "sigev_value" , & self . sigev_value) ;
1196
+ // Safe because we check the sigev_notify discriminant
1197
+ unsafe {
1198
+ match self . sigev_notify {
1199
+ libc:: SIGEV_KEVENT => {
1200
+ ds. field( "sigev_notify_kevent_flags" , & self . _sigev_un. _kevent_flags) ;
1201
+ }
1202
+ libc:: SIGEV_THREAD_ID => {
1203
+ ds. field( "sigev_notify_thread_id" , & self . _sigev_un. _threadid) ;
1204
+ }
1205
+ libc:: SIGEV_THREAD => {
1206
+ ds. field( "sigev_notify_function" , & self . _sigev_un. _sigev_thread. _function) ;
1207
+ ds. field( "sigev_notify_attributes" , & self . _sigev_un. _sigev_thread. _attribute) ;
1208
+ }
1209
+ _ => ( )
1210
+ } ;
1211
+ }
1212
+ ds. finish( )
1213
+ }
1214
+ }
1215
+
1216
+ impl PartialEq for sigevent {
1217
+ fn eq( & self , other: & Self ) -> bool {
1218
+ let mut equals = self . sigev_notify == other. sigev_notify;
1219
+ equals &= self . sigev_signo == other. sigev_signo;
1220
+ equals &= self . sigev_value == other. sigev_value;
1221
+ // Safe because we check the sigev_notify discriminant
1222
+ unsafe {
1223
+ match self . sigev_notify {
1224
+ libc:: SIGEV_KEVENT => {
1225
+ equals &= self . _sigev_un. _kevent_flags == other. _sigev_un. _kevent_flags;
1226
+ }
1227
+ libc:: SIGEV_THREAD_ID => {
1228
+ equals &= self . _sigev_un. _threadid == other. _sigev_un. _threadid;
1229
+ }
1230
+ libc:: SIGEV_THREAD => {
1231
+ equals &= self . _sigev_un. _sigev_thread == other. _sigev_un. _sigev_thread;
1232
+ }
1233
+ _ => /* The union field is don't care */ ( )
1234
+ }
1235
+ }
1236
+ equals
1237
+ }
1238
+ }
1239
+
1240
+ impl Eq for sigevent { }
1241
+
1242
+ impl hash:: Hash for sigevent {
1243
+ fn hash<H : hash:: Hasher >( & self , s: & mut H ) {
1244
+ self . sigev_notify. hash( s) ;
1245
+ self . sigev_signo. hash( s) ;
1246
+ self . sigev_value. hash( s) ;
1247
+ // Safe because we check the sigev_notify discriminant
1248
+ unsafe {
1249
+ match self . sigev_notify {
1250
+ libc:: SIGEV_KEVENT => {
1251
+ self . _sigev_un. _kevent_flags. hash( s) ;
1252
+ }
1253
+ libc:: SIGEV_THREAD_ID => {
1254
+ self . _sigev_un. _threadid. hash( s) ;
1255
+ }
1256
+ libc:: SIGEV_THREAD => {
1257
+ self . _sigev_un. _sigev_thread. hash( s) ;
1258
+ }
1259
+ _ => /* The union field is don't care */ ( )
1260
+ }
1261
+ }
1262
+ }
1263
+ }
1264
+ }
1265
+
1099
1266
/// Used to request asynchronous notification of the completion of certain
1100
1267
/// events, such as POSIX AIO and timers.
1101
1268
#[ repr( C ) ]
1102
- #[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq ) ]
1269
+ #[ derive( Clone , Debug , Eq , Hash , PartialEq ) ]
1270
+ // It can't be Copy on all platforms.
1271
+ #[ allow( missing_copy_implementations) ]
1103
1272
pub struct SigEvent {
1104
- sigevent: libc :: sigevent
1273
+ sigevent: libc_sigevent
1105
1274
}
1106
1275
1107
1276
impl SigEvent {
@@ -1119,7 +1288,7 @@ mod sigevent {
1119
1288
/// `SIGEV_SIGNAL`. That field is part of a union that shares space with the
1120
1289
/// more genuinely useful `sigev_notify_thread_id`
1121
1290
pub fn new( sigev_notify: SigevNotify ) -> SigEvent {
1122
- let mut sev: libc :: sigevent = unsafe { mem:: zeroed( ) } ;
1291
+ let mut sev: libc_sigevent = unsafe { mem:: zeroed( ) } ;
1123
1292
match sigev_notify {
1124
1293
SigevNotify :: SigevNone => {
1125
1294
sev. sigev_notify = libc:: SIGEV_NONE ;
@@ -1155,24 +1324,54 @@ mod sigevent {
1155
1324
sev. sigev_notify = libc:: SIGEV_THREAD_ID ;
1156
1325
sev. sigev_signo = signal as libc:: c_int;
1157
1326
sev. sigev_value. sival_ptr = si_value as * mut libc:: c_void;
1158
- sev. _sigev_un . _tid = thread_id;
1327
+ sev. sigev_notify_thread_id = thread_id;
1159
1328
}
1160
1329
}
1161
1330
SigEvent { sigevent: sev}
1162
1331
}
1163
1332
1164
1333
/// Return a copy of the inner structure
1334
+ #[ cfg( target_os = "freebsd" ) ]
1335
+ pub fn sigevent( & self ) -> libc:: sigevent {
1336
+ // Safe because they're really the same structure. See
1337
+ // https://github.com/rust-lang/libc/pull/2813
1338
+ unsafe {
1339
+ mem:: transmute:: <libc_sigevent, libc:: sigevent>( self . sigevent. clone( ) )
1340
+ }
1341
+ }
1342
+
1343
+ /// Return a copy of the inner structure
1344
+ #[ cfg( not( target_os = "freebsd" ) ) ]
1165
1345
pub fn sigevent( & self ) -> libc:: sigevent {
1166
1346
self . sigevent
1167
1347
}
1168
1348
1169
1349
/// Returns a mutable pointer to the `sigevent` wrapped by `self`
1350
+ #[ cfg( target_os = "freebsd" ) ]
1351
+ pub fn as_mut_ptr( & mut self ) -> * mut libc:: sigevent {
1352
+ // Safe because they're really the same structure. See
1353
+ // https://github.com/rust-lang/libc/pull/2813
1354
+ & mut self . sigevent as * mut libc_sigevent as * mut libc:: sigevent
1355
+ }
1356
+
1357
+ /// Returns a mutable pointer to the `sigevent` wrapped by `self`
1358
+ #[ cfg( not( target_os = "freebsd" ) ) ]
1170
1359
pub fn as_mut_ptr( & mut self ) -> * mut libc:: sigevent {
1171
1360
& mut self . sigevent
1172
1361
}
1173
1362
}
1174
1363
1175
1364
impl <' a> From <& ' a libc:: sigevent> for SigEvent {
1365
+ #[ cfg( target_os = "freebsd" ) ]
1366
+ fn from( sigevent: & libc:: sigevent) -> Self {
1367
+ // Safe because they're really the same structure. See
1368
+ // https://github.com/rust-lang/libc/pull/2813
1369
+ let sigevent = unsafe {
1370
+ mem:: transmute:: <libc:: sigevent, libc_sigevent>( * sigevent)
1371
+ } ;
1372
+ SigEvent { sigevent }
1373
+ }
1374
+ #[ cfg( not( target_os = "freebsd" ) ) ]
1176
1375
fn from( sigevent: & libc:: sigevent) -> Self {
1177
1376
SigEvent { sigevent: * sigevent }
1178
1377
}
0 commit comments