Skip to content

Commit 027c1bc

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. Signed-off-by: Yizhen Hu <huyizhen2024@163.com>
1 parent 00b3c78 commit 027c1bc

File tree

2 files changed

+54
-135
lines changed

2 files changed

+54
-135
lines changed

eloop.c

Lines changed: 54 additions & 106 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)
@@ -192,27 +187,20 @@ static inline void warn_too_many_fds()
192187
}
193188

194189
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
195-
fd_set *fds)
190+
struct pollfd *fds)
196191
{
197192
int i;
198193

199-
FD_ZERO(fds);
200-
201194
if (table->table == NULL)
202195
return;
203196

204-
for (i = 0; i < table->count; i++) {
205-
if (table->table[i].sock >= FD_SETSIZE) {
206-
warn_too_many_fds();
207-
continue;
208-
}
209-
FD_SET(table->table[i].sock, fds);
210-
}
197+
for (i = 0; i < table->count; i++)
198+
fds[i] = table->table[i].pfd;
211199
}
212200

213201

214202
static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
215-
fd_set *fds)
203+
struct pollfd *fds, int events)
216204
{
217205
int i;
218206

@@ -221,11 +209,8 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
221209

222210
table->changed = 0;
223211
for (i = 0; i < table->count; i++) {
224-
if (table->table[i].sock >= FD_SETSIZE) {
225-
return;
226-
}
227-
if (FD_ISSET(table->table[i].sock, fds)) {
228-
table->table[i].handler(table->table[i].sock,
212+
if (fds[i].revents & events) {
213+
table->table[i].handler(table->table[i].pfd.fd,
229214
table->table[i].eloop_data,
230215
table->table[i].user_data);
231216
if (table->changed)
@@ -239,10 +224,10 @@ static void eloop_sock_table_destroy(struct eloop_sock_table *table)
239224
{
240225
int rc, tc, sock;
241226

242-
if (table) {
227+
if (table->table) {
243228
tc = table->count;
244229
while (tc > 0) {
245-
sock = table->table[tc].sock;
230+
sock = table->table[tc].pfd.fd;
246231
rc = fcntl(sock, F_GETFD);
247232
if (rc != -1) {
248233
rc = close(sock);
@@ -256,54 +241,34 @@ static void eloop_sock_table_destroy(struct eloop_sock_table *table)
256241
}
257242
}
258243

259-
260-
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
261-
void *eloop_data, void *user_data)
244+
static int eloop_register_sock(struct pollfd pfd,
245+
eloop_sock_handler handler,
246+
void *eloop_data, void *user_data)
262247
{
263-
return eloop_register_sock(sock, EVENT_TYPE_READ, handler,
264-
eloop_data, user_data);
248+
return eloop_sock_table_add_sock(&eloop.sock_table, pfd, handler,
249+
eloop_data, user_data);
265250
}
266251

267252

268-
void eloop_unregister_read_sock(int sock)
253+
int eloop_register_read_sock(int sock, eloop_sock_handler handler,
254+
void *eloop_data, void *user_data)
269255
{
270-
eloop_unregister_sock(sock, EVENT_TYPE_READ);
256+
struct pollfd pfd = {0};
257+
pfd.fd = sock;
258+
pfd.events = POLLIN;
259+
return eloop_register_sock(pfd, handler, eloop_data, user_data);
271260
}
272261

273262

274-
static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type)
263+
static void eloop_unregister_sock(int sock)
275264
{
276-
switch (type) {
277-
case EVENT_TYPE_READ:
278-
return &eloop.readers;
279-
case EVENT_TYPE_WRITE:
280-
return &eloop.writers;
281-
case EVENT_TYPE_EXCEPTION:
282-
return &eloop.exceptions;
283-
}
284-
285-
return NULL;
265+
eloop_sock_table_remove_sock(&eloop.sock_table, sock);
286266
}
287267

288268

289-
int eloop_register_sock(int sock, eloop_event_type type,
290-
eloop_sock_handler handler,
291-
void *eloop_data, void *user_data)
292-
{
293-
struct eloop_sock_table *table;
294-
295-
table = eloop_get_sock_table(type);
296-
return eloop_sock_table_add_sock(table, sock, handler,
297-
eloop_data, user_data);
298-
}
299-
300-
301-
void eloop_unregister_sock(int sock, eloop_event_type type)
269+
void eloop_unregister_read_sock(int sock)
302270
{
303-
struct eloop_sock_table *table;
304-
305-
table = eloop_get_sock_table(type);
306-
eloop_sock_table_remove_sock(table, sock);
271+
eloop_unregister_sock(sock);
307272
}
308273

309274

@@ -484,43 +449,39 @@ int eloop_register_signal_reconfig(eloop_signal_handler handler,
484449
return eloop_register_signal(SIGHUP, handler, user_data);
485450
}
486451

452+
static inline int os_time_to_ms(struct os_time *tv)
453+
{
454+
return ((tv)->sec * 1000 + (tv)->usec / 1000);
455+
}
487456

488457
void eloop_run(void)
489458
{
490-
fd_set *rfds, *wfds, *efds;
491-
int res;
492-
struct timeval _tv;
459+
int res, timeout = 0;
493460
struct os_time tv, now;
494-
495-
rfds = malloc(sizeof(*rfds));
496-
wfds = malloc(sizeof(*wfds));
497-
efds = malloc(sizeof(*efds));
498-
if (rfds == NULL || wfds == NULL || efds == NULL) {
499-
printf("eloop_run - malloc failed\n");
500-
goto out;
501-
}
461+
struct pollfd *fds = NULL;
502462

503463
while (!eloop.terminate &&
504-
(eloop.timeout || eloop.readers.count > 0 ||
505-
eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
464+
(eloop.timeout || eloop.sock_table.count > 0)) {
506465
if (eloop.timeout) {
507466
os_get_time(&now);
508467
if (os_time_before(&now, &eloop.timeout->time))
509468
os_time_sub(&eloop.timeout->time, &now, &tv);
510469
else
511470
tv.sec = tv.usec = 0;
512-
_tv.tv_sec = tv.sec;
513-
_tv.tv_usec = tv.usec;
471+
timeout = os_time_to_ms(&tv);
472+
}
473+
474+
fds = (struct pollfd *)
475+
realloc(fds, eloop.sock_table.count * sizeof(struct eloop_sock));
476+
if (fds == NULL) {
477+
perror("eloop_run realloc");
478+
goto out;
514479
}
515480

516-
eloop_sock_table_set_fds(&eloop.readers, rfds);
517-
eloop_sock_table_set_fds(&eloop.writers, wfds);
518-
eloop_sock_table_set_fds(&eloop.exceptions, efds);
519-
res = select(eloop.max_sock < FD_SETSIZE ? eloop.max_sock + 1 : FD_SETSIZE,
520-
rfds, wfds, efds,
521-
eloop.timeout ? &_tv : NULL);
481+
eloop_sock_table_set_fds(&eloop.sock_table, fds);
482+
res = poll(fds, eloop.sock_table.count, eloop.timeout ? timeout : -1);
522483
if (res < 0 && errno != EINTR && errno != 0) {
523-
perror("select");
484+
perror("poll");
524485
goto out;
525486
}
526487
eloop_process_pending_signals();
@@ -542,16 +503,10 @@ void eloop_run(void)
542503

543504
if (res <= 0)
544505
continue;
545-
546-
eloop_sock_table_dispatch(&eloop.readers, rfds);
547-
eloop_sock_table_dispatch(&eloop.writers, wfds);
548-
eloop_sock_table_dispatch(&eloop.exceptions, efds);
506+
eloop_sock_table_dispatch(&eloop.sock_table, fds, POLLIN);
549507
}
550-
551508
out:
552-
free(rfds);
553-
free(wfds);
554-
free(efds);
509+
free(fds);
555510
}
556511

557512

@@ -571,9 +526,7 @@ void eloop_destroy(void)
571526
timeout = timeout->next;
572527
free(prev);
573528
}
574-
eloop_sock_table_destroy(&eloop.readers);
575-
eloop_sock_table_destroy(&eloop.writers);
576-
eloop_sock_table_destroy(&eloop.exceptions);
529+
eloop_sock_table_destroy(&eloop.sock_table);
577530
free(eloop.signals);
578531
}
579532

@@ -586,19 +539,14 @@ int eloop_terminated(void)
586539

587540
void eloop_wait_for_read_sock(int sock)
588541
{
589-
fd_set rfds;
542+
struct pollfd pfd;
590543

591544
if (sock < 0)
592545
return;
593546

594-
if (sock >= FD_SETSIZE) {
595-
warn_too_many_fds();
596-
return;
597-
}
598-
599-
FD_ZERO(&rfds);
600-
FD_SET(sock, &rfds);
601-
select(sock + 1, &rfds, NULL, NULL, NULL);
547+
pfd.fd = sock;
548+
pfd.events = POLLIN;
549+
poll(&pfd, 1, -1);
602550
}
603551

604552

include/eloop.h

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -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)