99#include <sys/socket.h>
1010#include <unistd.h>
1111#include <errno.h>
12+ #include <fcntl.h>
13+ #include <pthread.h>
14+ #include <memory.h>
15+ #include <sys/epoll.h>
1216
1317int test_communication (int from , int to )
1418{
@@ -116,6 +120,176 @@ int test_communication(int from, int to)
116120 return 0 ;
117121}
118122
123+ #define BUFFER_SIZE 1024
124+ #define MAX_EVENTS 10
125+
126+ typedef struct
127+ {
128+ int fd ;
129+ char buffer [BUFFER_SIZE ];
130+ } socket_data_t ;
131+
132+ void * epoll_thread (void * arg )
133+ {
134+ struct epoll_event events [MAX_EVENTS ];
135+ int n , i ;
136+ int epoll_fd = * (int * )arg ;
137+ // Quick'n'dirty way to read exactly 3 packets
138+ int num_events = 0 ;
139+ int sum = 0 ;
140+
141+ while (1 )
142+ {
143+ n = epoll_wait (epoll_fd , events , MAX_EVENTS , 5000 );
144+ if (n == -1 )
145+ {
146+ perror ("epoll_wait" );
147+ return (void * )0 ;
148+ }
149+ else if (n == 0 )
150+ {
151+ printf ("No events occurred within the timeout period.\n" );
152+ return (void * )0 ;
153+ }
154+
155+ for (i = 0 ; i < n ; i ++ )
156+ {
157+ socket_data_t * data = (socket_data_t * )events [i ].data .ptr ;
158+
159+ if (events [i ].events & EPOLLIN )
160+ {
161+ num_events ++ ;
162+
163+ while (1 )
164+ {
165+ ssize_t count = read (data -> fd , data -> buffer , BUFFER_SIZE - 1 );
166+
167+ if (count == -1 )
168+ {
169+ if (errno != EAGAIN )
170+ {
171+ perror ("read error" );
172+ close (data -> fd );
173+ free (data );
174+ return (void * )0 ;
175+ }
176+ break ;
177+ }
178+ else if (count == 0 )
179+ {
180+ // Connection closed by client
181+ close (data -> fd );
182+ free (data );
183+ return (void * )0 ;
184+ }
185+
186+ // Super-hacky, relies on packets arriving all at once, but
187+ // that should be the case anyway
188+ data -> buffer [count ] = '\0' ;
189+ sum += atoi (data -> buffer );
190+
191+ // Reset for next read
192+ memset (data -> buffer , 0 , BUFFER_SIZE );
193+ }
194+
195+ if (num_events >= 3 )
196+ {
197+ close (data -> fd );
198+ free (data );
199+ return (void * )sum ;
200+ }
201+ }
202+ else
203+ {
204+ printf ("Unexpected event on fd %d\n" , data -> fd );
205+ close (data -> fd );
206+ free (data );
207+ return (void * )0 ;
208+ }
209+ }
210+ }
211+ }
212+
213+ int wait_via_epoll ()
214+ {
215+ int epoll_fd = epoll_create1 (0 );
216+ if (epoll_fd == -1 )
217+ {
218+ perror ("epoll_create1" );
219+ exit (EXIT_FAILURE );
220+ }
221+
222+ int sockfd [2 ];
223+ if (socketpair (AF_UNIX , SOCK_STREAM , 0 , sockfd ) == -1 )
224+ {
225+ perror ("socketpair" );
226+ close (epoll_fd );
227+ exit (EXIT_FAILURE );
228+ }
229+
230+ int recv_fd = sockfd [0 ];
231+ int send_fd = sockfd [1 ];
232+
233+ int flags = fcntl (recv_fd , F_GETFL , 0 );
234+ fcntl (recv_fd , F_SETFL , flags | O_NONBLOCK );
235+
236+ socket_data_t * data = malloc (sizeof (socket_data_t ));
237+ if (!data )
238+ {
239+ perror ("malloc" );
240+ return -1 ;
241+ }
242+
243+ data -> fd = recv_fd ;
244+ memset (data -> buffer , 0 , BUFFER_SIZE );
245+
246+ struct epoll_event event ;
247+ event .events = EPOLLIN | EPOLLET ; // Edge-triggered mode
248+ event .data .ptr = data ;
249+
250+ if (epoll_ctl (epoll_fd , EPOLL_CTL_ADD , recv_fd , & event ) == -1 )
251+ {
252+ perror ("epoll_ctl failed" );
253+ free (data );
254+ return -1 ;
255+ }
256+
257+ pthread_attr_t attr ;
258+ pthread_attr_init (& attr );
259+ pthread_t thread ;
260+ pthread_create (& thread , & attr , epoll_thread , (void * )& epoll_fd );
261+
262+ struct timespec ts ;
263+ ts .tv_sec = 0 ;
264+ ts .tv_nsec = 100000000 ;
265+
266+ send (send_fd , "42" , 2 , 0 );
267+ nanosleep (& ts , NULL );
268+ send (send_fd , "69" , 2 , 0 );
269+ nanosleep (& ts , NULL );
270+ send (send_fd , "85" , 2 , 0 );
271+ nanosleep (& ts , NULL );
272+ close (send_fd );
273+
274+ void * result ;
275+ pthread_join (thread , & result );
276+ int sum = (int )result ;
277+ if (sum == 0 )
278+ {
279+ printf ("Error in epoll thread\n" );
280+ close (epoll_fd );
281+ return -1 ;
282+ }
283+ else if (sum != 196 )
284+ {
285+ printf ("Expected sum to be 196, got %d\n" , sum );
286+ close (epoll_fd );
287+ return -1 ;
288+ }
289+
290+ return 0 ;
291+ }
292+
119293int main ()
120294{
121295 int socks [2 ];
@@ -137,5 +311,10 @@ int main()
137311 return -1 ;
138312 }
139313
314+ if (wait_via_epoll () != 0 )
315+ {
316+ return -1 ;
317+ }
318+
140319 return 0 ;
141320}
0 commit comments