2 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
3 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
5 #include "cmogstored.h"
6 #include "compat_accept.h"
9 MOG_ACCEPT_FN" missing, rebuild on the same platform this runs on"
11 /* don't spam syslog on accept flood */
12 static void do_expire(struct mog_accept
*ac
)
16 static time_t last_expire
;
17 static pthread_mutex_t err_lock
= PTHREAD_MUTEX_INITIALIZER
;
19 CHECK(int, 0, pthread_mutex_lock(&err_lock
));
22 if (last_expire
== now
)
27 CHECK(int, 0, pthread_mutex_unlock(&err_lock
));
31 syslog(LOG_ERR
, MOG_ACCEPT_FN
" failed with: %m");
34 mog_fdmap_expire(ac
->svc
->idle_timeout
);
37 MOG_NOINLINE
static void accept_error_check(struct mog_accept
*ac
)
43 /* common error, nothing we can do about it */
45 /* we'll hit mog_thr_test_quit when we restart the loop */
48 assert(0 && "BUG, called accept on bad FD");
54 * listen socket could've been inherited from another process,
55 * we'll support that in the near future (like nginx/unicorn)
57 fd
= mog_fd_of(ac
)->fd
;
58 if (mog_set_nonblocking(fd
, false) != 0) {
59 assert(errno
!= EBADF
&& "unexpected EBADF");
61 "failed to make fd=%d blocking: %m", fd
);
63 syslog(LOG_DEBUG
, "made fd=%d blocking", fd
);
72 syslog(LOG_CRIT
, ENOSYS_msg
);
75 syslog(LOG_ERR
, MOG_ACCEPT_FN
" failed with: %m");
80 * passed as the start_routine argument to pthread_create.
81 * This function may run concurrently in multiple threads.
82 * The design of cmogstored assumes "wake-one" behavior for blocking
83 * accept()/accept4() callers. We will force accept_fd into blocking
84 * state if O_NONBLOCK is ever set (e.g. listen socket was inherited).
86 void *mog_accept_loop(void *arg
)
88 struct mog_accept
*ac
= arg
;
89 int accept_fd
= mog_fd_of(ac
)->fd
;
90 union mog_sockaddr msa
;
93 socklen_t salen
= (socklen_t
)sizeof(msa
);
97 client_fd
= mog_accept_fn(accept_fd
, &msa
.sa
, &salen
);
100 ac
->post_accept_fn(client_fd
, ac
, &msa
, salen
);
102 accept_error_check(ac
);