@@ -7365,8 +7365,8 @@ Random - Implementation
73657365#include <sys/time.h>
73667366#endif
73677367
7368- static volatile uint64_t fio___rand_state[4]; /* random state */
7369- static volatile size_t fio___rand_counter; /* seed counter */
7368+ static volatile uint64_t fio___rand_state[4] = {0} ; /* random state */
7369+ static volatile size_t fio___rand_counter = 0; /* seed counter */
73707370/* feeds random data to the algorithm through this 256 bit feed. */
73717371static volatile uint64_t fio___rand_buffer[4] = {0x9c65875be1fce7b9ULL,
73727372 0x7cc568e838f6a40d,
@@ -7429,14 +7429,14 @@ SFUNC uint64_t fio_rand64(void) {
74297429 /* modeled after xoroshiro128+, by David Blackman and Sebastiano Vigna */
74307430 uint64_t r = 0;
74317431 if (!((fio___rand_counter++) & (((size_t)1 << 12) - 1))) {
7432- /* re-seed state every 524,288 requests / 2^19 -1 attempts */
7432+ /* re-seed state every 4095 requests / 2^12 -1 attempts */
74337433 fio_rand_reseed();
74347434 }
74357435 const uint64_t s0[] = {fio___rand_state[0],
74367436 fio___rand_state[1],
74377437 fio___rand_state[2],
74387438 fio___rand_state[3]}; /* load to registers */
7439- uint64_t s1[4];
7439+ uint64_t s1[4] = {0} ;
74407440 {
74417441 const uint64_t mulp[] = {0x37701261ED6C16C7ULL,
74427442 0x764DBBB75F3B3E0DULL,
@@ -10859,6 +10859,8 @@ SFUNC size_t fio_sock_maximize_limits(size_t maximum_limit);
1085910859/**
1086010860 * Returns 0 on timeout, -1 on error or the events that are valid.
1086110861 *
10862+ * A zero timeout returns immediately.
10863+ *
1086210864 * Possible events are POLLIN | POLLOUT
1086310865 */
1086410866SFUNC short fio_sock_wait_io(int fd, short events, int timeout);
@@ -10873,6 +10875,16 @@ SFUNC short fio_sock_wait_io(int fd, short events, int timeout);
1087310875/** A helper macro that waits on a single IO with no callbacks (0 = no event) */
1087410876#define FIO_SOCK_WAIT_W(fd, timeout_) fio_sock_wait_io(fd, POLLOUT, timeout_)
1087510877
10878+ #ifdef POLLRDHUP
10879+ /** A helper macro that tests if a socket was closed. */
10880+ #define FIO_SOCK_IS_OPEN(fd) \
10881+ (!(fio_sock_wait_io(fd, (POLLOUT | POLLRDHUP), 0) & \
10882+ (POLLRDHUP | POLLHUP | POLLNVAL)))
10883+ #else
10884+ #define FIO_SOCK_IS_OPEN(fd) \
10885+ (!(fio_sock_wait_io(fd, POLLOUT, 0) & (POLLHUP | POLLNVAL)))
10886+ #endif
10887+
1087610888/* *****************************************************************************
1087710889IO Poll - Implementation (always static / inlined)
1087810890***************************************************************************** */
@@ -35286,6 +35298,13 @@ Copyright and License: see header file (000 copyright.h) or top of file
3528635298/** I would love to use fio_time_mono, but using time_real enables logging. */
3528735299#define FIO___IO_GET_TIME_MILLI() fio_time2milli(fio_time_real())
3528835300
35301+ /** Sets a flag in io->flag */
35302+ #define FIO___IO_FLAG_SET(io, flag_to_set) \
35303+ fio_atomic_or(&(io)->flags, flag_to_set)
35304+ /** unsets a flag in io->flag */
35305+ #define FIO___IO_FLAG_UNSET(io, flag_to_unset) \
35306+ fio_atomic_and(&(io)->flags, ~(flag_to_unset))
35307+
3528935308/* *****************************************************************************
3529035309IO environment support (`env`)
3529135310***************************************************************************** */
@@ -35531,8 +35550,9 @@ FIO_IFUNC void fio___io_init_protocol_test(fio_io_protocol_s *pr,
3553135550IO Reactor State Machine
3553235551***************************************************************************** */
3553335552
35534- #define FIO___IO_FLAG_WAKEUP (1U)
35535- #define FIO___IO_FLAG_CYCLING (2U)
35553+ #define FIO___IO_FLAG_WAKEUP (1U)
35554+ #define FIO___IO_FLAG_CYCLING (2U)
35555+ #define FIO___IO_FLAG_TICK_SET (4U)
3553635556
3553735557typedef struct {
3553835558 FIO_LIST_NODE node;
@@ -35570,6 +35590,32 @@ static struct FIO___IO_S {
3557035590 .shutdown_timeout = FIO_IO_SHUTDOWN_TIMEOUT,
3557135591};
3557235592
35593+ FIO_IFUNC void fio___io_defer_no_wakeup(void (*task)(void *, void *),
35594+ void *udata1,
35595+ void *udata2) {
35596+ fio_queue_push(&FIO___IO.queue, task, udata1, udata2);
35597+ }
35598+
35599+ FIO_SFUNC void fio___io_wakeup(void);
35600+ void fio_io_defer___(void);
35601+ /** Schedules a task for delayed execution. This function is thread-safe. */
35602+ SFUNC void fio_io_defer FIO_NOOP(void (*task)(void *, void *),
35603+ void *udata1,
35604+ void *udata2) {
35605+ fio_queue_push(&FIO___IO.queue, task, udata1, udata2);
35606+ fio___io_wakeup();
35607+ }
35608+
35609+ void fio_io_run_every___(void);
35610+ /** Schedules a timer bound task, see `fio_timer_schedule`. */
35611+ SFUNC void fio_io_run_every FIO_NOOP(fio_timer_schedule_args_s args) {
35612+ args.start_at = FIO___IO.tick;
35613+ fio_timer_schedule FIO_NOOP(&FIO___IO.timer, args);
35614+ }
35615+
35616+ /** Returns a pointer for the IO reactor's queue. */
35617+ SFUNC fio_queue_s *fio_io_queue(void) { return &FIO___IO.queue; }
35618+
3557335619/** Stopping the IO reactor. */
3557435620SFUNC void fio_io_stop(void) { fio_atomic_or_fetch(&FIO___IO.stop, 1); }
3557535621
@@ -35588,40 +35634,25 @@ SFUNC int fio_io_is_master(void) { return FIO___IO.root_pid == FIO___IO.pid; }
3558835634/** Returns true if the current process is a worker process. */
3558935635SFUNC int fio_io_is_worker(void) { return FIO___IO.is_worker; }
3559035636
35637+ FIO_SFUNC void fio___io_last_tick_update(void *ignr_1, void *ignr_2) {
35638+ FIO___IO_FLAG_UNSET(&FIO___IO, FIO___IO_FLAG_TICK_SET);
35639+ FIO___IO.tick = FIO___IO_GET_TIME_MILLI();
35640+ (void)ignr_1, (void)ignr_2;
35641+ }
35642+
3559135643/** Returns the last millisecond when the polled for IO events. */
35592- SFUNC int64_t fio_io_last_tick(void) { return FIO___IO.tick; }
35644+ SFUNC int64_t fio_io_last_tick(void) {
35645+ if (!(FIO___IO_FLAG_SET(&FIO___IO, FIO___IO_FLAG_TICK_SET) &
35646+ FIO___IO_FLAG_TICK_SET))
35647+ fio___io_defer_no_wakeup(fio___io_last_tick_update, NULL, NULL);
35648+ return FIO___IO.tick;
35649+ }
3559335650
3559435651/** Sets a signal to listen to for a hot restart (see `fio_io_restart`). */
3559535652SFUNC void fio_io_restart_on_signal(int signal) {
3559635653 FIO___IO.restart_signal = signal;
3559735654}
3559835655
35599- FIO_SFUNC void fio___io_wakeup(void);
35600- void fio_io_defer___(void);
35601- /** Schedules a task for delayed execution. This function is thread-safe. */
35602- SFUNC void fio_io_defer FIO_NOOP(void (*task)(void *, void *),
35603- void *udata1,
35604- void *udata2) {
35605- fio_queue_push(&FIO___IO.queue, task, udata1, udata2);
35606- fio___io_wakeup();
35607- }
35608-
35609- FIO_IFUNC void fio___io_defer_no_wakeup(void (*task)(void *, void *),
35610- void *udata1,
35611- void *udata2) {
35612- fio_queue_push(&FIO___IO.queue, task, udata1, udata2);
35613- }
35614-
35615- void fio_io_run_every___(void);
35616- /** Schedules a timer bound task, see `fio_timer_schedule`. */
35617- SFUNC void fio_io_run_every FIO_NOOP(fio_timer_schedule_args_s args) {
35618- args.start_at = FIO___IO.tick;
35619- fio_timer_schedule FIO_NOOP(&FIO___IO.timer, args);
35620- }
35621-
35622- /** Returns a pointer for the IO reactor's queue. */
35623- SFUNC fio_queue_s *fio_io_queue(void) { return &FIO___IO.queue; }
35624-
3562535656/** Returns the shutdown timeout for the reactor. */
3562635657SFUNC size_t fio_io_shutdown_timsout(void) { return FIO___IO.shutdown_timeout; }
3562735658
@@ -35653,11 +35684,6 @@ IO Type
3565335684#define FIO___IO_FLAG_POLL_SET \
3565435685 (FIO___IO_FLAG_POLLIN_SET | FIO___IO_FLAG_POLLOUT_SET)
3565535686
35656- #define FIO___IO_FLAG_SET(io, flag_to_set) \
35657- fio_atomic_or(&(io)->flags, flag_to_set)
35658- #define FIO___IO_FLAG_UNSET(io, flag_to_unset) \
35659- fio_atomic_and(&(io)->flags, ~(flag_to_unset))
35660-
3566135687static void fio___io_poll_on_data_schd(void *io);
3566235688static void fio___io_poll_on_ready_schd(void *io);
3566335689static void fio___io_poll_on_close_schd(void *io);
@@ -37790,6 +37816,9 @@ SFUNC fio_io_s *fio_io_connect FIO_NOOP(fio_io_connect_args_s args) {
3779037816/* *****************************************************************************
3779137817IO Reactor Finish
3779237818***************************************************************************** */
37819+ #undef FIO___IO_FLAG_SET
37820+ #undef FIO___IO_FLAG_UNSET
37821+ #undef FIO___IO_GET_TIME_MILLI
3779337822#endif /* FIO_IO */
3779437823/* ************************************************************************* */
3779537824#if !defined(FIO_INCLUDE_FILE) /* Dev test - ignore line */
@@ -42676,7 +42705,8 @@ int fio_http_cookie_set___(void); /* IDE Marker */
4267642705SFUNC int fio_http_cookie_set FIO_NOOP(fio_http_s *h,
4267742706 fio_http_cookie_args_s cookie) {
4267842707 FIO_ASSERT_DEBUG(h, "Can't set cookie for NULL HTTP handler!");
42679- if (!h || (h->state & (FIO_HTTP_STATE_FINISHED | FIO_HTTP_STATE_STREAMING)))
42708+ if (!h || ((h->state & (FIO_HTTP_STATE_FINISHED | FIO_HTTP_STATE_STREAMING)) |
42709+ (h->writer != fio____http_write_start)))
4268042710 return -1;
4268142711 /* promises that some warnings print only once. */
4268242712 static unsigned int warn_illegal = 0;
@@ -46021,7 +46051,8 @@ FIO_SFUNC void fio___http_perform_user_callback(void *cb_, void *h_) {
4602146051 } cb = {.ptr = cb_};
4602246052 fio_http_s *h = (fio_http_s *)h_;
4602346053 fio___http_connection_s *c = (fio___http_connection_s *)fio_http_cdata(h);
46024- if (FIO_LIKELY(fio_io_is_open(c->io)))
46054+
46055+ if (FIO_LIKELY(FIO_SOCK_IS_OPEN(fio_io_fd(c->io))))
4602546056 cb.fn(h);
4602646057 fio_http_free(h);
4602746058}
@@ -46035,7 +46066,7 @@ FIO_SFUNC void fio___http_perform_user_upgrade_callback_websocket(void *cb_,
4603546066 fio_http_s *h = (fio_http_s *)h_;
4603646067 fio___http_connection_s *c = (fio___http_connection_s *)fio_http_cdata(h);
4603746068 struct fio___http_connection_http_s old = c->state.http;
46038- if (cb.fn(h))
46069+ if (!FIO_LIKELY(fio_io_is_open(c->io)) || cb.fn(h))
4603946070 goto refuse_upgrade;
4604046071 if (c->h) /* request after WebSocket Upgrade? an attack vector? */
4604146072 goto refuse_upgrade;
@@ -46101,7 +46132,7 @@ FIO_SFUNC void fio___http_perform_user_upgrade_callback_sse(void *cb_,
4610146132 } cb = {.ptr = cb_};
4610246133 fio_http_s *h = (fio_http_s *)h_;
4610346134 fio___http_connection_s *c = (fio___http_connection_s *)fio_http_cdata(h);
46104- if (cb.fn(h))
46135+ if (!FIO_LIKELY(fio_io_is_open(c->io)) || cb.fn(h))
4610546136 goto refuse_upgrade;
4610646137 if (c->h) /* request after eventsource? an attack vector? */
4610746138 goto refuse_upgrade;
@@ -46702,19 +46733,21 @@ HTTP/1.1 Protocol
4670246733
4670346734FIO_SFUNC int fio___http1_process_data(fio_io_s *io,
4670446735 fio___http_connection_s *c) {
46705- (void)io, (void)c;
46706- size_t consumed = fio_http1_parse(&c->state.http.parser,
46707- FIO_BUF_INFO2(c->buf, c->len),
46708- (void *)c);
46709- if (!consumed)
46710- goto nothing_consumed;
46711- if (consumed == FIO_HTTP1_PARSER_ERROR)
46712- goto http1_error;
46713- c->len -= consumed;
46714- if (c->len)
46715- FIO_MEMMOVE(c->buf, c->buf + consumed, c->len);
46716- if (c->suspend)
46717- return -1;
46736+ (void)io;
46737+ for (;;) {
46738+ size_t consumed = fio_http1_parse(&c->state.http.parser,
46739+ FIO_BUF_INFO2(c->buf, c->len),
46740+ (void *)c);
46741+ if (!consumed)
46742+ goto nothing_consumed;
46743+ if (consumed == FIO_HTTP1_PARSER_ERROR)
46744+ goto http1_error;
46745+ c->len -= consumed;
46746+ if (c->len)
46747+ FIO_MEMMOVE(c->buf, c->buf + consumed, c->len);
46748+ if (c->suspend)
46749+ return -1;
46750+ }
4671846751 return 0;
4671946752
4672046753nothing_consumed:
0 commit comments