Skip to content

Commit 24cba20

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 24cba20

File tree

2 files changed

+54
-122
lines changed

2 files changed

+54
-122
lines changed

eloop.c

Lines changed: 53 additions & 92 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

@@ -67,9 +68,8 @@ int os_get_time(struct os_time *t)
6768
} \
6869
} while (0)
6970

70-
7171
struct eloop_sock {
72-
int sock;
72+
struct pollfd pfd;
7373
void *eloop_data;
7474
void *user_data;
7575
eloop_sock_handler handler;
@@ -99,11 +99,7 @@ struct eloop_sock_table {
9999
struct eloop_data {
100100
void *user_data;
101101

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

108104
struct eloop_timeout *timeout;
109105

@@ -128,7 +124,7 @@ int eloop_init(void *user_data)
128124

129125

130126
static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
131-
int sock, eloop_sock_handler handler,
127+
struct pollfd pfd, eloop_sock_handler handler,
132128
void *eloop_data, void *user_data)
133129
{
134130
struct eloop_sock *tmp;
@@ -142,14 +138,12 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table,
142138
if (tmp == NULL)
143139
return -ENOMEM;
144140

145-
tmp[table->count].sock = sock;
141+
tmp[table->count].pfd = pfd;
146142
tmp[table->count].eloop_data = eloop_data;
147143
tmp[table->count].user_data = user_data;
148144
tmp[table->count].handler = handler;
149145
table->count++;
150146
table->table = tmp;
151-
if (sock > eloop.max_sock)
152-
eloop.max_sock = sock;
153147
table->changed = 1;
154148

155149
return 0;
@@ -165,7 +159,7 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
165159
return;
166160

167161
for (i = 0; i < table->count; i++) {
168-
if (table->table[i].sock == sock)
162+
if (table->table[i].pfd.fd == sock)
169163
break;
170164
}
171165
if (i == table->count)
@@ -181,22 +175,20 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
181175

182176

183177
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
184-
fd_set *fds)
178+
struct pollfd *fds)
185179
{
186180
int i;
187181

188-
FD_ZERO(fds);
189-
190182
if (table->table == NULL)
191183
return;
192184

193185
for (i = 0; i < table->count; i++)
194-
FD_SET(table->table[i].sock, fds);
186+
fds[i] = table->table[i].pfd;
195187
}
196188

197189

198190
static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
199-
fd_set *fds)
191+
struct pollfd *fds, int events)
200192
{
201193
int i;
202194

@@ -205,8 +197,8 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
205197

206198
table->changed = 0;
207199
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,
200+
if (fds[i].revents & events) {
201+
table->table[i].handler(table->table[i].pfd.fd,
210202
table->table[i].eloop_data,
211203
table->table[i].user_data);
212204
if (table->changed)
@@ -220,10 +212,10 @@ static void eloop_sock_table_destroy(struct eloop_sock_table *table)
220212
{
221213
int rc, tc, sock;
222214

223-
if (table) {
215+
if (table->table) {
224216
tc = table->count;
225217
while (tc > 0) {
226-
sock = table->table[tc].sock;
218+
sock = table->table[tc].pfd.fd;
227219
rc = fcntl(sock, F_GETFD);
228220
if (rc != -1) {
229221
rc = close(sock);
@@ -237,54 +229,34 @@ static void eloop_sock_table_destroy(struct eloop_sock_table *table)
237229
}
238230
}
239231

240-
241-
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
242-
void *eloop_data, void *user_data)
243-
{
244-
return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
245-
eloop_data, user_data);
246-
}
247-
248-
249-
void eloop_unregister_read_sock(int sock)
232+
static int eloop_register_sock(struct pollfd pfd,
233+
eloop_sock_handler handler,
234+
void *eloop_data, void *user_data)
250235
{
251-
eloop_unregister_sock(sock, EVENT_TYPE_READ);
236+
return eloop_sock_table_add_sock(&eloop.sock_table, pfd, handler,
237+
eloop_data, user_data);
252238
}
253239

254240

255-
static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
241+
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
242+
void *eloop_data, void *user_data)
256243
{
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;
244+
struct pollfd pfd = {0};
245+
pfd.fd = sock;
246+
pfd.events = POLLIN;
247+
return eloop_register_sock(pfd, handler, eloop_data, user_data);
267248
}
268249

269250

270-
int eloop_register_sock(int sock, eloop_event_type type,
271-
eloop_sock_handler handler,
272-
void *eloop_data, void *user_data)
251+
static void eloop_unregister_sock(int sock)
273252
{
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);
253+
eloop_sock_table_remove_sock(&eloop.sock_table, sock);
279254
}
280255

281256

282-
void eloop_unregister_sock(int sock, eloop_event_type type)
257+
void eloop_unregister_read_sock(int sock)
283258
{
284-
struct eloop_sock_table *table;
285-
286-
table = eloop_get_sock_table(type);
287-
eloop_sock_table_remove_sock(table, sock);
259+
eloop_unregister_sock(sock);
288260
}
289261

290262

@@ -465,42 +437,39 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
465437
return eloop_register_signal(SIGHUP, handler, user_data);
466438
}
467439

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

469445
void eloop_run(void)
470446
{
471-
fd_set *rfds, *wfds, *efds;
472-
int res;
473-
struct timeval _tv;
447+
int res, timeout = 0;
474448
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-
}
449+
struct pollfd *fds = NULL;
483450

484451
while (!eloop.terminate &&
485-
(eloop.timeout || eloop.readers.count > 0 ||
486-
eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
452+
(eloop.timeout || eloop.sock_table.count > 0)) {
487453
if (eloop.timeout) {
488454
os_get_time(&now);
489455
if (os_time_before(&now, &eloop.timeout->time))
490456
os_time_sub(&eloop.timeout->time, &now, &tv);
491457
else
492458
tv.sec = tv.usec = 0;
493-
_tv.tv_sec = tv.sec;
494-
_tv.tv_usec = tv.usec;
459+
timeout = os_time_to_ms(&tv);
460+
}
461+
462+
fds = (struct pollfd *)
463+
realloc(fds, eloop.sock_table.count * sizeof(struct eloop_sock));
464+
if (fds == NULL) {
465+
perror("eloop_run realloc");
466+
goto out;
495467
}
496468

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);
469+
eloop_sock_table_set_fds(&eloop.sock_table, fds);
470+
res = poll(fds, eloop.sock_table.count, eloop.timeout ? timeout : -1);
502471
if (res < 0 && errno != EINTR && errno != 0) {
503-
perror("select");
472+
perror("poll");
504473
goto out;
505474
}
506475
eloop_process_pending_signals();
@@ -522,16 +491,10 @@ void eloop_run(void)
522491

523492
if (res <= 0)
524493
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);
494+
eloop_sock_table_dispatch(&eloop.sock_table, fds, POLLIN);
529495
}
530-
531496
out:
532-
free(rfds);
533-
free(wfds);
534-
free(efds);
497+
free(fds);
535498
}
536499

537500

@@ -551,9 +514,7 @@ void eloop_destroy(void)
551514
timeout = timeout->next;
552515
free(prev);
553516
}
554-
eloop_sock_table_destroy(&eloop.readers);
555-
eloop_sock_table_destroy(&eloop.writers);
556-
eloop_sock_table_destroy(&eloop.exceptions);
517+
eloop_sock_table_destroy(&eloop.sock_table);
557518
free(eloop.signals);
558519
}
559520

@@ -566,14 +527,14 @@ int eloop_terminated(void)
566527

567528
void eloop_wait_for_read_sock(int sock)
568529
{
569-
fd_set rfds;
530+
struct pollfd pfd;
570531

571532
if (sock < 0)
572533
return;
573534

574-
FD_ZERO(&rfds);
575-
FD_SET(sock, &rfds);
576-
select(sock + 1, &rfds, NULL, NULL, NULL);
535+
pfd.fd = sock;
536+
pfd.events = POLLIN;
537+
poll(&pfd, 1, -1);
577538
}
578539

579540

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)