1- use std:: { io, path:: PathBuf } ;
1+ use std:: {
2+ io,
3+ os:: fd:: AsRawFd ,
4+ path:: PathBuf ,
5+ thread:: { self , JoinHandle } ,
6+ } ;
27
38use anyhow:: { Context , bail} ;
49use aya:: {
@@ -10,11 +15,7 @@ use checks::Checks;
1015use globset:: { Glob , GlobSet , GlobSetBuilder } ;
1116use libc:: c_char;
1217use log:: { error, info, warn} ;
13- use tokio:: {
14- io:: unix:: AsyncFd ,
15- sync:: { mpsc, watch} ,
16- task:: JoinHandle ,
17- } ;
18+ use tokio:: sync:: { mpsc, watch} ;
1819
1920use crate :: { config:: BpfConfig , event:: Event , host_info, metrics:: EventCounter } ;
2021
@@ -211,36 +212,56 @@ impl Bpf {
211212 // Gather events from the ring buffer and print them out.
212213 pub fn start (
213214 mut self ,
214- mut running : watch:: Receiver < bool > ,
215+ running : watch:: Receiver < bool > ,
215216 event_counter : EventCounter ,
216217 ) -> JoinHandle < anyhow:: Result < ( ) > > {
217218 info ! ( "Starting BPF worker..." ) ;
218219
219- tokio:: spawn ( async move {
220- let rb = self . take_ringbuffer ( ) ?;
221- let mut fd = AsyncFd :: new ( rb) ?;
220+ thread:: spawn ( move || {
221+ let mut rb = self . take_ringbuffer ( ) ?;
222+
223+ let rb_event = epoll:: Event :: new ( epoll:: Events :: EPOLLIN , 0 ) ;
224+ let poller = match epoll:: create ( false ) {
225+ Ok ( p) => p,
226+ Err ( e) => bail ! ( "Failed to create epoll: {e:?}" ) ,
227+ } ;
228+ if let Err ( e) = epoll:: ctl (
229+ poller,
230+ epoll:: ControlOptions :: EPOLL_CTL_ADD ,
231+ rb. as_raw_fd ( ) ,
232+ rb_event,
233+ ) {
234+ bail ! ( "Failed to add ringbuffer to epoll: {e:?}" ) ;
235+ }
222236
223237 loop {
224- tokio:: select! {
225- guard = fd. readable_mut( ) => {
226- let mut guard = guard
227- . context( "ringbuffer guard held while runtime is stopping" ) ?;
228- let ringbuf = guard. get_inner_mut( ) ;
229- while let Some ( event) = ringbuf. next( ) {
238+ if running. has_changed ( ) ? && !* running. borrow ( ) {
239+ info ! ( "Stopping BPF worker..." ) ;
240+ break ;
241+ }
242+
243+ if self . paths_config . has_changed ( ) ? {
244+ self . load_paths ( ) . context ( "Failed to load paths" ) ?;
245+ }
246+
247+ match epoll:: wait ( poller, 100 , & mut [ rb_event] ) {
248+ Ok ( n) if n != 0 => {
249+ while let Some ( event) = rb. next ( ) {
230250 let event: & event_t = unsafe { & * ( event. as_ptr ( ) as * const _ ) } ;
231251 let event = match Event :: try_from ( event) {
232252 Ok ( event) => {
233253 // If the event is monitored by parent, we need to check
234254 // its host path, but we don't have that context here,
235255 // so we let the event go into HostScanner and make the
236256 // decision there.
237- if !event. is_monitored_by_parent( ) &&
238- event. is_ignored( & self . paths_globset) {
257+ if !event. is_monitored_by_parent ( )
258+ && event. is_ignored ( & self . paths_globset )
259+ {
239260 event_counter. dropped ( ) ;
240261 continue ;
241262 }
242263 event
243- } ,
264+ }
244265 Err ( e) => {
245266 error ! ( "Failed to parse event: '{e}'" ) ;
246267 event_counter. dropped ( ) ;
@@ -249,25 +270,18 @@ impl Bpf {
249270 } ;
250271
251272 event_counter. added ( ) ;
252- if self . tx. send ( event) . await . is_err( ) {
273+ if self . tx . blocking_send ( event) . is_err ( ) {
253274 info ! ( "No BPF consumers left, stopping..." ) ;
254275 break ;
255276 }
256277 }
257- guard. clear_ready( ) ;
258- } ,
259- _ = self . paths_config. changed( ) => {
260- self . load_paths( ) . context( "Failed to load paths" ) ?;
261- } ,
262- _ = running. changed( ) => {
263- if !* running. borrow( ) {
264- info!( "Stopping BPF worker..." ) ;
265- break ;
266- }
267- } ,
278+ }
279+ Ok ( _) => { }
280+ Err ( e) => bail ! ( "Failed to wait for ringbuffer events: {e:?}" ) ,
268281 }
269282 }
270283
284+ info ! ( "Stopping BPF worker..." ) ;
271285 Ok ( ( ) )
272286 } )
273287 }
@@ -289,8 +303,8 @@ mod bpf_tests {
289303
290304 use super :: * ;
291305
292- #[ tokio :: test]
293- async fn test_basic ( ) {
306+ #[ test]
307+ fn test_basic ( ) {
294308 if let Ok ( value) = std:: env:: var ( "FACT_LOGLEVEL" ) {
295309 let value = value. to_lowercase ( ) ;
296310 if value == "debug" || value == "trace" {
@@ -312,7 +326,7 @@ mod bpf_tests {
312326
313327 let handle = bpf. start ( run_rx, exporter. metrics . bpf_worker . clone ( ) ) ;
314328
315- tokio :: time :: sleep ( Duration :: from_millis ( 500 ) ) . await ;
329+ thread :: sleep ( Duration :: from_millis ( 500 ) ) ;
316330
317331 // Create a file
318332 let file = NamedTempFile :: new_in ( & monitored_path) . expect ( "Failed to create temporary file" ) ;
@@ -383,24 +397,26 @@ mod bpf_tests {
383397 // Close the file, removing it
384398 file. close ( ) . expect ( "Failed to close temp file" ) ;
385399
386- let wait = timeout ( Duration :: from_secs ( 1 ) , async move {
387- for expected in expected_events {
388- println ! ( "expected: {expected:#?}" ) ;
389- while let Some ( event) = rx. recv ( ) . await {
390- println ! ( "{event:#?}" ) ;
391- if event == expected {
392- println ! ( "Found!" ) ;
393- break ;
400+ tokio:: runtime:: Runtime :: new ( ) . unwrap ( ) . block_on ( async {
401+ let wait = timeout ( Duration :: from_secs ( 1 ) , async {
402+ for expected in expected_events {
403+ println ! ( "expected: {expected:#?}" ) ;
404+ while let Some ( event) = rx. recv ( ) . await {
405+ println ! ( "{event:#?}" ) ;
406+ if event == expected {
407+ println ! ( "Found!" ) ;
408+ break ;
409+ }
394410 }
395411 }
412+ } ) ;
413+
414+ tokio:: select! {
415+ res = wait => res. unwrap( ) ,
396416 }
397417 } ) ;
398418
399- tokio:: select! {
400- res = wait => res. unwrap( ) ,
401- res = handle => res. unwrap( ) . unwrap( ) ,
402- }
403-
404419 run_tx. send ( false ) . unwrap ( ) ;
420+ handle. join ( ) . unwrap ( ) . unwrap ( ) ;
405421 }
406422}
0 commit comments