Fix wssshc SIGINT crashes and multiple tunnel closure issues

- Fix double-free corruption in cleanup_tunnel by removing SSL freeing
- Add global shutdown flag for proper thread synchronization
- Improve SIGINT handling with better thread cleanup timing
- Send tunnel_close acknowledgment when receiving tunnel_close from server
- Prevent threads from accessing freed tunnel structures
- Ensure proper resource management during shutdown
parent 6d1bf50b
......@@ -41,6 +41,9 @@ int active_tunnels_count = 0;
int active_tunnels_capacity = 0;
pthread_mutex_t tunnel_mutex = PTHREAD_MUTEX_INITIALIZER;
// Global shutdown flag for threads
volatile int global_shutdown = 0;
frame_buffer_t *frame_buffer_init() {
frame_buffer_t *fb = malloc(sizeof(frame_buffer_t));
if (!fb) return NULL;
......@@ -257,6 +260,9 @@ void handle_tunnel_request(SSL *ssl, const char *request_id, int debug, const ch
void cleanup_tunnel(int debug) {
pthread_mutex_lock(&tunnel_mutex);
// Set global shutdown flag to signal all threads to stop
global_shutdown = 1;
// First, mark all tunnels as inactive to signal threads to stop
for (int i = 0; i < active_tunnels_count; i++) {
if (active_tunnels[i]) {
......@@ -264,12 +270,12 @@ void cleanup_tunnel(int debug) {
}
}
// Give threads a moment to stop using SSL connections
// Give threads a moment to stop using resources
pthread_mutex_unlock(&tunnel_mutex);
usleep(100000); // 100ms
usleep(200000); // 200ms - increased timeout for better thread cleanup
pthread_mutex_lock(&tunnel_mutex);
// Now safely clean up
// Now safely clean up - don't free SSL contexts as they're managed at connection level
for (int i = 0; i < active_tunnels_count; i++) {
if (active_tunnels[i]) {
if (active_tunnels[i]->sock >= 0) {
......@@ -284,10 +290,10 @@ void cleanup_tunnel(int debug) {
close(active_tunnels[i]->local_sock);
active_tunnels[i]->local_sock = -1;
}
if (active_tunnels[i]->ssl) {
SSL_free(active_tunnels[i]->ssl);
// Don't free SSL here - it's managed at the connection level
// Just set the pointer to NULL to prevent use-after-free
active_tunnels[i]->ssl = NULL;
}
if (active_tunnels[i]->outgoing_buffer) {
frame_buffer_free(active_tunnels[i]->outgoing_buffer);
}
......@@ -787,7 +793,7 @@ void send_tunnel_close(SSL *ssl, const char *request_id, int debug) {
}
}
void handle_tunnel_close(SSL *ssl __attribute__((unused)), const char *request_id, int debug) {
void handle_tunnel_close(SSL *ssl, const char *request_id, int debug) {
pthread_mutex_lock(&tunnel_mutex);
tunnel_t *tunnel = find_tunnel_by_request_id(request_id);
if (tunnel) {
......@@ -797,6 +803,8 @@ void handle_tunnel_close(SSL *ssl __attribute__((unused)), const char *request_i
printf("[DEBUG - Tunnel] Tunnel %s closed\n", request_id);
fflush(stdout);
}
// Send tunnel_close back to server to acknowledge
send_tunnel_close(ssl, request_id, debug);
}
pthread_mutex_unlock(&tunnel_mutex);
}
......
......@@ -57,6 +57,7 @@ extern int active_tunnels_count;
extern int active_tunnels_capacity;
extern pthread_mutex_t tunnel_mutex;
extern pthread_mutex_t ssl_mutex; // For synchronizing SSL operations
extern volatile int global_shutdown; // Global flag to signal threads to stop
// Function declarations
frame_buffer_t *frame_buffer_init(void);
......
......@@ -253,6 +253,9 @@ int connect_to_server(const wssshc_config_t *config) {
char buffer[BUFFER_SIZE];
int bytes_read;
// Reset global shutdown flag for new connection
global_shutdown = 0;
// Clean up any leftover tunnel state from previous connection
cleanup_tunnel(config->debug);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment