Skip to content

Commit 6195d11

Browse files
committed
lldpad eloop select change to poll
In an environment with 576 virtual NICs, when the function eloop_sock_table_dispatch calls FD_ISSET, the value of file descriptor table->table[i].sock exceeds 1024 (the kernel fds structure has only 1024 bits). As a result, the glibc determines that a buffer overflow occurs and aborts the process. To solve this problem, we change select to poll because poll has no restriction on the fd size. Poll allows file descriptors to listen to different events, such as POLLIN and POLLOUT. Therefore, no need to create different queues for different events, we delete writers and exceptions and rename readers to sock_table.
1 parent 3689d5a commit 6195d11

File tree

2 files changed

+55
-121
lines changed

2 files changed

+55
-121
lines changed

eloop.c

Lines changed: 54 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <sys/time.h>
2121
#include <unistd.h>
2222
#include <fcntl.h>
23+
#include <poll.h>
2324
#include "eloop.h"
2425
#include "include/messages.h"
2526

@@ -69,7 +70,7 @@ int os_get_time(struct os_time *t)
6970

7071

7172
struct eloop_sock {
72-
int sock;
73+
struct pollfd pfd;
7374
void *eloop_data;
7475
void *user_data;
7576
eloop_sock_handler handler;
@@ -99,11 +100,7 @@ struct eloop_sock_table {
99100
struct eloop_data {
100101
void *user_data;
101102

102-
int max_sock;
103-
104-
struct eloop_sock_table readers;
105-
struct eloop_sock_table writers;
106-
struct eloop_sock_table exceptions;
103+
struct eloop_sock_table sock_table;
107104

108105
struct eloop_timeout *timeout;
109106

@@ -128,7 +125,7 @@ int eloop_init(void *user_data)
128125

129126

130127
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
131-
int sock, eloop_sock_handler handler,
128+
struct pollfd pfd, eloop_sock_handler handler,
132129
void *eloop_data, void *user_data)
133130
{
134131
struct eloop_sock *tmp;
@@ -142,14 +139,12 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
142139
if (tmp == NULL)
143140
return -ENOMEM;
144141

145-
tmp[table->count].sock = sock;
142+
tmp[table->count].pfd = pfd;
146143
tmp[table->count].eloop_data = eloop_data;
147144
tmp[table->count].user_data = user_data;
148145
tmp[table->count].handler = handler;
149146
table->count++;
150147
table->table = tmp;
151-
if (sock > eloop.max_sock)
152-
eloop.max_sock = sock;
153148
table->changed = 1;
154149

155150
return 0;
@@ -165,7 +160,7 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
165160
return;
166161

167162
for (i = 0; i < table->count; i++) {
168-
if (table->table[i].sock == sock)
163+
if (table->table[i].pfd.fd == sock)
169164
break;
170165
}
171166
if (i == table->count)
@@ -181,22 +176,20 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
181176

182177

183178
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
184-
fd_set *fds)
179+
struct pollfd *fds)
185180
{
186181
int i;
187182

188-
FD_ZERO(fds);
189-
190183
if (table->table == NULL)
191184
return;
192185

193186
for (i = 0; i < table->count; i++)
194-
FD_SET(table->table[i].sock, fds);
187+
fds[i] = table->table[i].pfd;
195188
}
196189

197190

198191
static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
199-
fd_set *fds)
192+
struct pollfd *fds, int events)
200193
{
201194
int i;
202195

@@ -205,8 +198,8 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
205198

206199
table->changed = 0;
207200
for (i = 0; i < table->count; i++) {
208-
if (FD_ISSET(table->table[i].sock, fds)) {
209-
table->table[i].handler(table->table[i].sock,
201+
if (fds[i].revents & events) {
202+
table->table[i].handler(table->table[i].pfd.fd,
210203
table->table[i].eloop_data,
211204
table->table[i].user_data);
212205
if (table->changed)
@@ -220,10 +213,10 @@ static void eloop_sock_table_destroy(struct eloop_sock_table *table)
220213
{
221214
int rc, tc, sock;
222215

223-
if (table) {
216+
if (table->table) {
224217
tc = table->count;
225218
while (tc > 0) {
226-
sock = table->table[tc].sock;
219+
sock = table->table[tc].pfd.fd;
227220
rc = fcntl(sock, F_GETFD);
228221
if (rc != -1) {
229222
rc = close(sock);
@@ -237,54 +230,34 @@ static void eloop_sock_table_destroy(struct eloop_sock_table *table)
237230
}
238231
}
239232

240-
241-
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
242-
void *eloop_data, void *user_data)
233+
static int eloop_register_sock(struct pollfd pfd,
234+
eloop_sock_handler handler,
235+
void *eloop_data, void *user_data)
243236
{
244-
return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
245-
eloop_data, user_data);
237+
return eloop_sock_table_add_sock(&eloop.sock_table, pfd, handler,
238+
eloop_data, user_data);
246239
}
247240

248241

249-
void eloop_unregister_read_sock(int sock)
242+
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
243+
void *eloop_data, void *user_data)
250244
{
251-
eloop_unregister_sock(sock, EVENT_TYPE_READ);
245+
struct pollfd pfd = {0};
246+
pfd.fd = sock;
247+
pfd.events = POLLIN;
248+
return eloop_register_sock(pfd, handler, eloop_data, user_data);
252249
}
253250

254251

255-
static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
252+
static void eloop_unregister_sock(int sock)
256253
{
257-
switch (type) {
258-
case EVENT_TYPE_READ:
259-
return &eloop.readers;
260-
case EVENT_TYPE_WRITE:
261-
return &eloop.writers;
262-
case EVENT_TYPE_EXCEPTION:
263-
return &eloop.exceptions;
264-
}
265-
266-
return NULL;
254+
eloop_sock_table_remove_sock(&eloop.sock_table, sock);
267255
}
268256

269257

270-
int eloop_register_sock(int sock, eloop_event_type type,
271-
eloop_sock_handler handler,
272-
void *eloop_data, void *user_data)
273-
{
274-
struct eloop_sock_table *table;
275-
276-
table = eloop_get_sock_table(type);
277-
return eloop_sock_table_add_sock(table, sock, handler,
278-
eloop_data, user_data);
279-
}
280-
281-
282-
void eloop_unregister_sock(int sock, eloop_event_type type)
258+
void eloop_unregister_read_sock(int sock)
283259
{
284-
struct eloop_sock_table *table;
285-
286-
table = eloop_get_sock_table(type);
287-
eloop_sock_table_remove_sock(table, sock);
260+
eloop_unregister_sock(sock);
288261
}
289262

290263

@@ -465,42 +438,39 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
465438
return eloop_register_signal(SIGHUP, handler, user_data);
466439
}
467440

441+
static inline int os_time_to_ms(struct os_time *tv)
442+
{
443+
return ((tv)->sec * 1000 + (tv)->usec / 1000);
444+
}
468445

469446
void eloop_run(void)
470447
{
471-
fd_set *rfds, *wfds, *efds;
472-
int res;
473-
struct timeval _tv;
448+
int res, timeout = 0;
474449
struct os_time tv, now;
475-
476-
rfds = malloc(sizeof(*rfds));
477-
wfds = malloc(sizeof(*wfds));
478-
efds = malloc(sizeof(*efds));
479-
if (rfds == NULL || wfds == NULL || efds == NULL) {
480-
printf("eloop_run - malloc failed\n");
481-
goto out;
482-
}
450+
struct pollfd *fds = NULL;
483451

484452
while (!eloop.terminate &&
485-
(eloop.timeout || eloop.readers.count > 0 ||
486-
eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
453+
(eloop.timeout || eloop.sock_table.count > 0)) {
487454
if (eloop.timeout) {
488455
os_get_time(&now);
489456
if (os_time_before(&now, &eloop.timeout->time))
490457
os_time_sub(&eloop.timeout->time, &now, &tv);
491458
else
492459
tv.sec = tv.usec = 0;
493-
_tv.tv_sec = tv.sec;
494-
_tv.tv_usec = tv.usec;
460+
timeout = os_time_to_ms(&tv);
461+
}
462+
463+
fds = (struct pollfd *)
464+
realloc(fds, eloop.sock_table.count * sizeof(struct eloop_sock));
465+
if (fds == NULL) {
466+
perror("eloop_run realloc");
467+
goto out;
495468
}
496469

497-
eloop_sock_table_set_fds(&eloop.readers, rfds);
498-
eloop_sock_table_set_fds(&eloop.writers, wfds);
499-
eloop_sock_table_set_fds(&eloop.exceptions, efds);
500-
res = select(eloop.max_sock + 1, rfds, wfds, efds,
501-
eloop.timeout ? &_tv : NULL);
470+
eloop_sock_table_set_fds(&eloop.sock_table, fds);
471+
res = poll(fds, eloop.sock_table.count, eloop.timeout ? timeout : -1);
502472
if (res < 0 && errno != EINTR && errno != 0) {
503-
perror("select");
473+
perror("poll");
504474
goto out;
505475
}
506476
eloop_process_pending_signals();
@@ -522,16 +492,11 @@ void eloop_run(void)
522492

523493
if (res <= 0)
524494
continue;
525-
526-
eloop_sock_table_dispatch(&eloop.readers, rfds);
527-
eloop_sock_table_dispatch(&eloop.writers, wfds);
528-
eloop_sock_table_dispatch(&eloop.exceptions, efds);
495+
eloop_sock_table_dispatch(&eloop.sock_table, fds, POLLIN);
529496
}
530-
531497
out:
532-
free(rfds);
533-
free(wfds);
534-
free(efds);
498+
if (fds)
499+
free(fds);
535500
}
536501

537502

@@ -551,9 +516,7 @@ void eloop_destroy(void)
551516
timeout = timeout->next;
552517
free(prev);
553518
}
554-
eloop_sock_table_destroy(&eloop.readers);
555-
eloop_sock_table_destroy(&eloop.writers);
556-
eloop_sock_table_destroy(&eloop.exceptions);
519+
eloop_sock_table_destroy(&eloop.sock_table);
557520
free(eloop.signals);
558521
}
559522

@@ -566,14 +529,14 @@ int eloop_terminated(void)
566529

567530
void eloop_wait_for_read_sock(int sock)
568531
{
569-
fd_set rfds;
532+
struct pollfd pfd;
570533

571534
if (sock < 0)
572535
return;
573536

574-
FD_ZERO(&rfds);
575-
FD_SET(sock, &rfds);
576-
select(sock + 1, &rfds, NULL, NULL, NULL);
537+
pfd.fd = sock;
538+
pfd.events = POLLIN;
539+
poll(&pfd, 1, -1);
577540
}
578541

579542

include/eloop.h

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
* ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts
2828
*/
2929
#define ELOOP_ALL_CTX (void *) -1
30-
30+
3131
/**
3232
* eloop_event_type - eloop socket event type for eloop_register_sock()
3333
* @EVENT_TYPE_READ: Socket has data available for reading
@@ -111,35 +111,6 @@ int eloop_register_read_sock(int sock, eloop_sock_handler handler,
111111
*/
112112
void eloop_unregister_read_sock(int sock);
113113

114-
/**
115-
* eloop_register_sock - Register handler for socket events
116-
* @sock: File descriptor number for the socket
117-
* @type: Type of event to wait for
118-
* @handler: Callback function to be called when the event is triggered
119-
* @eloop_data: Callback context data (eloop_ctx)
120-
* @user_data: Callback context data (sock_ctx)
121-
* Returns: 0 on success, -1 on failure
122-
*
123-
* Register an event notifier for the given socket's file descriptor. The
124-
* handler function will be called whenever the that event is triggered for the
125-
* socket. The handler function is responsible for clearing the event after
126-
* having processed it in order to avoid eloop from calling the handler again
127-
* for the same event.
128-
*/
129-
int eloop_register_sock(int sock, eloop_event_type type,
130-
eloop_sock_handler handler,
131-
void *eloop_data, void *user_data);
132-
133-
/**
134-
* eloop_unregister_sock - Unregister handler for socket events
135-
* @sock: File descriptor number for the socket
136-
* @type: Type of event for which sock was registered
137-
*
138-
* Unregister a socket event notifier that was previously registered with
139-
* eloop_register_sock().
140-
*/
141-
void eloop_unregister_sock(int sock, eloop_event_type type);
142-
143114
/**
144115
* eloop_register_event - Register handler for generic events
145116
* @event: Event to wait (eloop implementation specific)

0 commit comments

Comments
 (0)