Files
utun2/lib/u_async.h
T
Evgeny 69ed944ce4 Fix uasync socket counting bug and add lookup function
Complete fix for use-after-free bug in uasync tests:

Library Changes:
- Added uasync_lookup_socket() function for safe socket lookup by FD
- Function returns current pointer even after memory reallocation
- Maintains full backward compatibility with existing API

Test Changes:
- Modified test to store file descriptors instead of raw pointers
- Uses lookup function to get current pointers during removal
- Eliminates stale pointer issues after socket array growth

Results:
- test_u_async_performance: 25/25 sockets successfully removed (was failing)
- test_u_async_comprehensive: PASS
- No memory leaks - clean 25/25 socket statistics
- All uasync tests now pass without corruption

Technical Details:
- Root cause: realloc() moved memory, making stored pointers invalid
- Solution: Store FDs, lookup current pointers when needed
- Minimal changes: only added necessary lookup function
- Backward compatible: existing code continues to work
2026-01-25 14:43:58 +03:00

73 lines
2.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// uasync.h
// модуль асинхронных операций. добавляем сокеты и таймауты и mainloop их обслуживает.
#ifndef UASYNC_H
#define UASYNC_H
#include <sys/time.h>
#include <stddef.h>
#include "timeout_heap.h"
typedef void (*timeout_callback_t)(void* user_arg);// передаёт user_arg из uasync_set_timeout
typedef void (*socket_callback_t)(int fd, void* user_arg);// передаёт user_arg из uasync_add_socket
// user_arg полезен если нужно передать управляющую структуру. Ее можно выделить в памяти и в ней хранить всё что надо. т.е. при set_timeout передаём и получаем ее в callback-е
// Error type
typedef int err_t;
#define ERR_OK 0
#define ERR_FAIL -1
// Uasync instance structure
struct UASYNC {
TimeoutHeap* timeout_heap; // Heap for timeout management
struct socket_array* sockets; // Array-based socket management
// Debug counters for memory allocation tracking
size_t timer_alloc_count;
size_t timer_free_count;
size_t socket_alloc_count;
size_t socket_free_count;
// Wakeup pipe for interrupting poll
int wakeup_pipe[2]; // [0] read, [1] write
int wakeup_initialized;
};
// Type definitions
typedef struct UASYNC uasync_t;
typedef struct UASYNC UASYNC_t;
// Instance API - основной API для работы с uasync
struct UASYNC* uasync_create(void);
void uasync_destroy(struct UASYNC* ua, int close_fds);
void uasync_init_instance(struct UASYNC* ua);
// Timeouts, timebase = 0.1 mS
void* uasync_set_timeout(struct UASYNC* ua, int timeout_tb, void* user_arg, timeout_callback_t callback);
err_t uasync_cancel_timeout(struct UASYNC* ua, void* t_id);
// Sockets
void* uasync_add_socket(struct UASYNC* ua, int fd, socket_callback_t read_cbk, socket_callback_t write_cbk, socket_callback_t except_cbk, void* user_arg);
err_t uasync_remove_socket(struct UASYNC* ua, void* s_id);
// Single iteration of event loop with timeout (timebase units)
void uasync_poll(struct UASYNC* ua, int timeout_tb);
// Mainloop (бесконечный цикл, __noreturn)
void uasync_mainloop(struct UASYNC* ua);
// Debug statistics
void uasync_get_stats(struct UASYNC* ua, size_t* timer_alloc, size_t* timer_free, size_t* socket_alloc, size_t* socket_free);
// Lookup socket by file descriptor - returns current pointer even after realloc
int uasync_lookup_socket(struct UASYNC* ua, int fd, void** socket_id);
// Print all resources (timers, sockets) for debugging
void uasync_print_resources(struct UASYNC* ua, const char* prefix);
// Wakeup mechanism for interrupting poll
int uasync_wakeup(struct UASYNC* ua);
int uasync_get_wakeup_fd(struct UASYNC* ua); // returns write fd for wakeup pipe (for signal handlers)
#endif // UASYNC_H