@@ -14,6 +14,7 @@ fn main() {
14
14
test_not_fully_closed_fd ( ) ;
15
15
test_closed_fd ( ) ;
16
16
test_two_epoll_instance ( ) ;
17
+ test_no_notification_for_unregister_flag ( ) ;
17
18
test_epoll_ctl_mod ( ) ;
18
19
test_epoll_ctl_del ( ) ;
19
20
test_pointer ( ) ;
@@ -68,7 +69,7 @@ fn test_epoll_socketpair() {
68
69
u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ,
69
70
} ;
70
71
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
71
- assert_ne ! ( res, - 1 ) ;
72
+ assert_eq ! ( res, 0 ) ;
72
73
73
74
// Check result from epoll_wait.
74
75
let expected_event = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) ;
@@ -99,6 +100,8 @@ fn test_epoll_socketpair() {
99
100
check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
100
101
}
101
102
103
+ // This test first registers a file description with a flag that does not lead to notification,
104
+ // then EPOLL_CTL_MOD to add another flag that will lead to notification.
102
105
fn test_epoll_ctl_mod ( ) {
103
106
// Create an epoll instance.
104
107
let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
@@ -109,37 +112,27 @@ fn test_epoll_ctl_mod() {
109
112
let res = unsafe { libc:: socketpair ( libc:: AF_UNIX , libc:: SOCK_STREAM , 0 , fds. as_mut_ptr ( ) ) } ;
110
113
assert_eq ! ( res, 0 ) ;
111
114
112
- // Write to fd[0].
113
- let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
114
- let res = unsafe { libc:: write ( fds[ 0 ] , data as * const libc:: c_void , 5 ) } ;
115
- assert_eq ! ( res, 5 ) ;
116
-
117
- // Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET.
118
- // (Not using checked cast as EPOLLET wraps around.)
119
- let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) } ;
115
+ // Register fd[1] with EPOLLIN|EPOLLET.
116
+ let mut ev = libc:: epoll_event {
117
+ events : ( libc:: EPOLLIN | libc:: EPOLLET ) as _ ,
118
+ u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ,
119
+ } ;
120
120
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
121
- assert_ne ! ( res, - 1 ) ;
121
+ assert_eq ! ( res, 0 ) ;
122
122
123
- // Check result from epoll_wait.
124
- let expected_event = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) ;
125
- let expected_value = u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ;
126
- check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
123
+ // Check result from epoll_wait. No notification would be returned.
124
+ check_epoll_wait :: < 8 > ( epfd, & [ ] ) ;
127
125
128
- // Test EPOLLRDHUP .
126
+ // Use EPOLL_CTL_MOD to change to EPOLLOUT flag .
129
127
let mut ev = libc:: epoll_event {
130
- events : ( libc:: EPOLLIN | libc :: EPOLLOUT | libc:: EPOLLET | libc :: EPOLLRDHUP ) as _ ,
128
+ events : ( libc:: EPOLLOUT | libc:: EPOLLET ) as _ ,
131
129
u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ,
132
130
} ;
133
131
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_MOD , fds[ 1 ] , & mut ev) } ;
134
- assert_ne ! ( res, -1 ) ;
135
-
136
- // Close the other side of the socketpair to invoke EPOLLRDHUP.
137
- let res = unsafe { libc:: close ( fds[ 0 ] ) } ;
138
132
assert_eq ! ( res, 0 ) ;
139
133
140
- // Check result from epoll_wait.
141
- let expected_event =
142
- u32:: try_from ( libc:: EPOLLRDHUP | libc:: EPOLLIN | libc:: EPOLLOUT | libc:: EPOLLHUP ) . unwrap ( ) ;
134
+ // Check result from epoll_wait. EPOLLOUT notification is expected.
135
+ let expected_event = u32:: try_from ( libc:: EPOLLOUT ) . unwrap ( ) ;
143
136
let expected_value = u64:: try_from ( fds[ 1 ] ) . unwrap ( ) ;
144
137
check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
145
138
}
@@ -162,10 +155,12 @@ fn test_epoll_ctl_del() {
162
155
// Register fd[1] with EPOLLIN|EPOLLOUT|EPOLLET
163
156
let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) } ;
164
157
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
165
- assert_ne ! ( res, - 1 ) ;
158
+ assert_eq ! ( res, 0 ) ;
166
159
167
160
// Test EPOLL_CTL_DEL.
168
- check_epoll_wait :: < 0 > ( epfd, & [ ] ) ;
161
+ let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_DEL , fds[ 1 ] , & mut ev) } ;
162
+ assert_eq ! ( res, 0 ) ;
163
+ check_epoll_wait :: < 8 > ( epfd, & [ ] ) ;
169
164
}
170
165
171
166
// This test is for one fd registered under two different epoll instance.
@@ -189,9 +184,9 @@ fn test_two_epoll_instance() {
189
184
// Register one side of the socketpair with EPOLLIN | EPOLLOUT | EPOLLET.
190
185
let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fds[ 1 ] ) . unwrap ( ) } ;
191
186
let res = unsafe { libc:: epoll_ctl ( epfd1, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
192
- assert_ne ! ( res, - 1 ) ;
187
+ assert_eq ! ( res, 0 ) ;
193
188
let res = unsafe { libc:: epoll_ctl ( epfd2, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
194
- assert_ne ! ( res, - 1 ) ;
189
+ assert_eq ! ( res, 0 ) ;
195
190
196
191
// Notification should be received from both instance of epoll.
197
192
let expected_event = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) ;
@@ -219,9 +214,9 @@ fn test_two_same_fd_in_same_epoll_instance() {
219
214
// Register both fd to the same epoll instance.
220
215
let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : 5 as u64 } ;
221
216
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
222
- assert_ne ! ( res, - 1 ) ;
217
+ assert_eq ! ( res, 0 ) ;
223
218
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , newfd, & mut ev) } ;
224
- assert_ne ! ( res, - 1 ) ;
219
+ assert_eq ! ( res, 0 ) ;
225
220
226
221
// Write to the socketpair.
227
222
let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
@@ -254,7 +249,7 @@ fn test_epoll_eventfd() {
254
249
// Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
255
250
let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fd) . unwrap ( ) } ;
256
251
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fd, & mut ev) } ;
257
- assert_ne ! ( res, - 1 ) ;
252
+ assert_eq ! ( res, 0 ) ;
258
253
259
254
// Check result from epoll_wait.
260
255
let expected_event = u32:: try_from ( libc:: EPOLLIN | libc:: EPOLLOUT ) . unwrap ( ) ;
@@ -277,7 +272,7 @@ fn test_pointer() {
277
272
let mut ev =
278
273
libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : data. expose_provenance ( ) as u64 } ;
279
274
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
280
- assert_ne ! ( res, - 1 ) ;
275
+ assert_eq ! ( res, 0 ) ;
281
276
}
282
277
283
278
// When read/write happened on one side of the socketpair, only the other side will be notified.
@@ -294,10 +289,10 @@ fn test_epoll_socketpair_both_sides() {
294
289
// Register both fd to the same epoll instance.
295
290
let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : fds[ 0 ] as u64 } ;
296
291
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 0 ] , & mut ev) } ;
297
- assert_ne ! ( res, - 1 ) ;
292
+ assert_eq ! ( res, 0 ) ;
298
293
let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : fds[ 1 ] as u64 } ;
299
294
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
300
- assert_ne ! ( res, - 1 ) ;
295
+ assert_eq ! ( res, 0 ) ;
301
296
302
297
// Write to fds[1].
303
298
let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
@@ -340,7 +335,7 @@ fn test_closed_fd() {
340
335
// Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
341
336
let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fd) . unwrap ( ) } ;
342
337
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fd, & mut ev) } ;
343
- assert_ne ! ( res, - 1 ) ;
338
+ assert_eq ! ( res, 0 ) ;
344
339
345
340
// Write to the eventfd instance.
346
341
let sized_8_data: [ u8 ; 8 ] = 1_u64 . to_ne_bytes ( ) ;
@@ -377,7 +372,7 @@ fn test_not_fully_closed_fd() {
377
372
// Register eventfd with EPOLLIN | EPOLLOUT | EPOLLET
378
373
let mut ev = libc:: epoll_event { events : EPOLL_IN_OUT_ET , u64 : u64:: try_from ( fd) . unwrap ( ) } ;
379
374
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fd, & mut ev) } ;
380
- assert_ne ! ( res, - 1 ) ;
375
+ assert_eq ! ( res, 0 ) ;
381
376
382
377
// Close the original fd that being used to register with epoll.
383
378
let res = unsafe { libc:: close ( fd) } ;
@@ -423,7 +418,7 @@ fn test_event_overwrite() {
423
418
u64 : u64:: try_from ( fd) . unwrap ( ) ,
424
419
} ;
425
420
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fd, & mut ev) } ;
426
- assert_ne ! ( res, - 1 ) ;
421
+ assert_eq ! ( res, 0 ) ;
427
422
428
423
// Read from the eventfd instance.
429
424
let mut buf: [ u8 ; 8 ] = [ 0 ; 8 ] ;
@@ -454,13 +449,13 @@ fn test_socketpair_read() {
454
449
u64 : fds[ 0 ] as u64 ,
455
450
} ;
456
451
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 0 ] , & mut ev) } ;
457
- assert_ne ! ( res, - 1 ) ;
452
+ assert_eq ! ( res, 0 ) ;
458
453
let mut ev = libc:: epoll_event {
459
454
events : ( libc:: EPOLLIN | libc:: EPOLLOUT | libc:: EPOLLET ) as _ ,
460
455
u64 : fds[ 1 ] as u64 ,
461
456
} ;
462
457
let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
463
- assert_ne ! ( res, - 1 ) ;
458
+ assert_eq ! ( res, 0 ) ;
464
459
465
460
// Write 5 bytes to fds[1].
466
461
let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
@@ -501,3 +496,35 @@ fn test_socketpair_read() {
501
496
let expected_value = fds[ 1 ] as u64 ;
502
497
check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
503
498
}
499
+
500
+ // This is to test whether flag that we don't register won't trigger notification.
501
+ fn test_no_notification_for_unregister_flag ( ) {
502
+ // Create an epoll instance.
503
+ let epfd = unsafe { libc:: epoll_create1 ( 0 ) } ;
504
+ assert_ne ! ( epfd, -1 ) ;
505
+
506
+ // Create a socketpair instance.
507
+ let mut fds = [ -1 , -1 ] ;
508
+ let res = unsafe { libc:: socketpair ( libc:: AF_UNIX , libc:: SOCK_STREAM , 0 , fds. as_mut_ptr ( ) ) } ;
509
+ assert_eq ! ( res, 0 ) ;
510
+
511
+ // Register fd[0] with EPOLLOUT|EPOLLET.
512
+ let mut ev = libc:: epoll_event {
513
+ events : ( libc:: EPOLLOUT | libc:: EPOLLET ) as _ ,
514
+ u64 : u64:: try_from ( fds[ 0 ] ) . unwrap ( ) ,
515
+ } ;
516
+ let res = unsafe { libc:: epoll_ctl ( epfd, libc:: EPOLL_CTL_ADD , fds[ 1 ] , & mut ev) } ;
517
+ assert_eq ! ( res, 0 ) ;
518
+
519
+ // Write to fd[1].
520
+ let data = "abcde" . as_bytes ( ) . as_ptr ( ) ;
521
+ let res: i32 =
522
+ unsafe { libc:: write ( fds[ 1 ] , data as * const libc:: c_void , 5 ) . try_into ( ) . unwrap ( ) } ;
523
+ assert_eq ! ( res, 5 ) ;
524
+
525
+ // Check result from epoll_wait. Since we didn't register EPOLLIN flag, the notification won't
526
+ // contain EPOLLIN even though fds[0] is now readable.
527
+ let expected_event = u32:: try_from ( libc:: EPOLLOUT ) . unwrap ( ) ;
528
+ let expected_value = u64:: try_from ( fds[ 0 ] ) . unwrap ( ) ;
529
+ check_epoll_wait :: < 8 > ( epfd, & [ ( expected_event, expected_value) ] ) ;
530
+ }
0 commit comments