Skip to content

Commit d7039a5

Browse files
committed
Convert fd_list_t to plain array
free() is not safe in fork()ed child when using threads. Convert fd_list_t linked list to plain array in order to avoid free() call.
1 parent 772173f commit d7039a5

File tree

4 files changed

+23
-21
lines changed

4 files changed

+23
-21
lines changed

libhttpd/api.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,6 @@ int port;
262262
free(new);
263263
return (NULL);
264264
}
265-
if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
266-
close(sock);
267-
free(new);
268-
return (NULL);
269-
}
270265
# ifdef SO_REUSEADDR
271266
opt = 1;
272267
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(int)) < 0) {

src/gateway.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ main_loop(void)
397397
debug(LOG_ERR, "Could not create web server: %s", strerror(errno));
398398
exit(1);
399399
}
400+
register_fd_cleanup_on_fork(webserver->serverSock);
400401

401402
debug(LOG_DEBUG, "Assigning callbacks to web server");
402403
httpdAddCContent(webserver, "/", "wifidog", 0, NULL, http_callback_wifidog);

src/safe.c

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,22 @@
4242
static void cleanup_fds(void);
4343

4444
/** List of fd's to close on fork. */
45-
typedef struct _fd_list {
46-
int fd; /**< @brief file descriptor */
47-
struct _fd_list *next; /**< @brief linked list pointer */
48-
} fd_list_t;
49-
50-
static fd_list_t *fd_list = NULL;
45+
typedef int fd_list_t;
46+
static fd_list_t fd_list[MAX_FD_CLEANUP];
5147

5248
/** Clean up all the registered fds. Frees the list as it goes.
5349
* XXX This should only be run by CHILD processes.
5450
*/
5551
static void
5652
cleanup_fds(void)
5753
{
58-
fd_list_t *entry;
54+
unsigned int i;
5955

60-
while (NULL != (entry = fd_list)) {
61-
close(entry->fd);
62-
fd_list = entry->next;
63-
free(entry);
56+
for (i = 0; i < sizeof(fd_list) / sizeof(int); i++) {
57+
if (fd_list[i]) {
58+
close(fd_list[i]);
59+
fd_list[i] = 0;
60+
}
6461
}
6562
}
6663

@@ -70,11 +67,18 @@ cleanup_fds(void)
7067
void
7168
register_fd_cleanup_on_fork(const int fd)
7269
{
73-
fd_list_t *entry = safe_malloc(sizeof(fd_list_t));
74-
75-
entry->fd = fd;
76-
entry->next = fd_list;
77-
fd_list = entry;
70+
unsigned int i;
71+
for (i = 0; i < sizeof(fd_list) / sizeof(int); i++) {
72+
if (!fd_list[i]) {
73+
break;
74+
}
75+
}
76+
if (MAX_FD_CLEANUP == i) {
77+
debug(LOG_CRIT, "Trying to register more than %d fds for cleanup on fork",
78+
MAX_FD_CLEANUP);
79+
exit(1);
80+
}
81+
fd_list[i] = fd;
7882
}
7983

8084
/** Allocate zero-filled ram or die.

src/safe.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include <sys/types.h> /* For fork */
3333
#include <unistd.h> /* For fork */
3434

35+
#define MAX_FD_CLEANUP 16
36+
3537
/** Register an fd for auto-cleanup on fork() */
3638
void register_fd_cleanup_on_fork(const int);
3739

0 commit comments

Comments
 (0)