Test HUP registration failure and teardown with pending TCP writes
This commit is contained in:
1 parent
1ce285c09b
commit
d0edacb7b9
1 file changed
+41
-2
@@ -38,7 +38,8 @@ void* __real_uasync_add_socket_t(struct UASYNC*, socket_t, socket_t_callback_t,
|
||||
socket_t_callback_t, const char*, void*);
|
||||
void* __wrap_uasync_add_socket_t(struct UASYNC* ua, socket_t fd, socket_t_callback_t read, socket_t_callback_t write,
|
||||
socket_t_callback_t error, const char* name, void* arg) {
|
||||
if (fail_read && (!strcmp(name, "udp_flow") || !strcmp(name, "icmp_raw"))) { fail_read = 0; return NULL; }
|
||||
if ((fail_read == 1 && (!strcmp(name, "udp_flow") || !strcmp(name, "icmp_raw"))) ||
|
||||
(fail_read == 2 && !strcmp(name, "tcp_io"))) { fail_read = 0; return NULL; }
|
||||
return __real_uasync_add_socket_t(ua, fd, read, write, error, name, arg);
|
||||
}
|
||||
void* __real_uasync_set_timeout(struct UASYNC*, int, void*, timeout_callback_t, const char*);
|
||||
@@ -227,6 +228,43 @@ static int instance_rollback(int kind) {
|
||||
free_config(cfg); uasync_destroy(ua, 0); return 0;
|
||||
}
|
||||
|
||||
struct tcp_owner { struct tcp_conn* tc; int error; };
|
||||
static void tcp_failed(struct tcp_conn* tc, int err, void* arg) {
|
||||
struct tcp_owner* owner = arg; owner->tc = NULL; owner->error = err; tcp_conn_destroy(tc);
|
||||
}
|
||||
|
||||
// Проверяем destroy из ошибки восстановления poll и независимую ошибку ожидающей записи при HUP.
|
||||
static int tcp_hup_failure(int writing) {
|
||||
struct UASYNC* ua = uasync_create(); CHECK(ua);
|
||||
int fds[2]; CHECK_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, fds), 0);
|
||||
CHECK_EQ(socket_set_nonblocking(fds[0]), 0); CHECK_EQ(socket_set_nonblocking(fds[1]), 0);
|
||||
int sndbuf = 1024; CHECK_EQ(setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)), 0);
|
||||
struct tcp_owner owner = {0};
|
||||
owner.tc = tcp_conn_create(ua, fds[0], 64, 32768, 2, 0, 0, NULL, tcp_failed, &owner); CHECK(owner.tc);
|
||||
if (writing) {
|
||||
tcp_conn_pause_read(owner.tc);
|
||||
struct ll_entry* e = queue_entry_new_from_pool(owner.tc->entry_pool); CHECK(e);
|
||||
e->dgram = memory_pool_alloc(owner.tc->data_pool); CHECK(e->dgram); memset(e->dgram, 0, 32768); e->len = 32768;
|
||||
queue_data_put(owner.tc->write_queue, e); CHECK(owner.tc && owner.tc->write_buf);
|
||||
close(fds[1]);
|
||||
for (int i = 0; i < 20 && owner.tc; i++) uasync_poll(ua, 0);
|
||||
CHECK(!owner.tc && (owner.error == EPIPE || owner.error == ECONNRESET));
|
||||
} else {
|
||||
uint8_t bytes[512] = {0}; CHECK_EQ(send(fds[1], bytes, sizeof(bytes), MSG_NOSIGNAL), sizeof(bytes));
|
||||
close(fds[1]); for (int i = 0; i < 10; i++) uasync_poll(ua, 0);
|
||||
CHECK(owner.tc && owner.tc->hup_received && !owner.tc->socket_id);
|
||||
CHECK_EQ(owner.tc->read_queue->count, 2); fail_read = 2;
|
||||
while (owner.tc && owner.tc->read_queue->head) {
|
||||
struct memory_pool* pool = owner.tc->data_pool;
|
||||
struct ll_entry* e = queue_data_get(owner.tc->read_queue); CHECK(e);
|
||||
memory_pool_free(pool, e->dgram); queue_entry_free(e);
|
||||
}
|
||||
CHECK(!owner.tc && owner.error == ENOMEM && !fail_read);
|
||||
}
|
||||
uasync_drain_immediate(ua); CHECK_EQ(ua->socket_alloc_count, ua->socket_free_count);
|
||||
uasync_destroy(ua, 0); return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const struct regression_case cases[] = {
|
||||
{"UDP flow allocation", udp_failures, 0}, {"UDP socket", udp_failures, 1},
|
||||
@@ -240,7 +278,8 @@ int main(int argc, char** argv) {
|
||||
{"ICMP expiry and renewal", icmp_failures, 3}, {"Shared contexts and listener rollback", ownership, 0},
|
||||
{"Instance UDP rollback", instance_rollback, 0}, {"Instance ICMP rollback", instance_rollback, 1},
|
||||
{"Instance listener rollback", instance_rollback, 2}, {"Instance optional ICMP", instance_rollback, 3},
|
||||
{"Instance raw registration rollback", instance_rollback, 4}
|
||||
{"Instance raw registration rollback", instance_rollback, 4},
|
||||
{"TCP HUP restore failure", tcp_hup_failure, 0}, {"TCP HUP pending write failure", tcp_hup_failure, 1}
|
||||
};
|
||||
return regression_run(argc, argv, cases, sizeof(cases) / sizeof(cases[0]));
|
||||
}
|
||||
Reference in new issue
Block a user