sslh-ev: keep track of forked processes

This commit is contained in:
Yves Rűtschlé committed 2025-08-12 23:05:24 +02:00
1 parent eb6a3c6724
commit 2624877232
7 files changed
+72 -37

No files matched your search

+2 -1
View File
@@ -46,6 +46,7 @@
#if 0
#define DEBUG 1
#include <stdio.h>
#endif
typedef void* hash_item;
@@ -169,7 +170,7 @@ int hash_insert(hash* h, hash_item new)
if (distance(index, h, curr_item) < distance(index, h, new)) {
gap_set(h->data, index, new);
#if DEBUG
fprintf(stderr, "intermediate insert [%d] at %d\n", new->pid, index);
fprintf(stderr, "intermediate insert at %d\n", index);
#endif
new = curr_item;
}
+21 -18
View File
@@ -26,6 +26,14 @@
#include "probe.h"
#include "log.h"
/* Struct to keep track of an association of a forked PID to its
* listening socket and its protocol */
struct pid2proto {
pid_t pid;
struct listen_endpoint* endpoint;
struct sslhcfg_protocols_item* proto;
};
int tidy_connection(struct connection *cnx, struct loop_info* fd_info)
{
@@ -130,10 +138,7 @@ static int pid_cmp(hash_item item1, hash_item item2)
/* When a child has died, update the counts appropriately */
void decrease_forked_connection(struct loop_info* loop, pid_t pid) {
struct pid2proto p2p = {
.pid = pid,
.proto = NULL
};
struct pid2proto p2p = { .pid = pid };
struct pid2proto* found = hash_find(loop->pid2proto, &p2p);
dec_proto_connections(found->proto);
dec_listen_connections(found->endpoint);
@@ -142,20 +147,18 @@ void decrease_forked_connection(struct loop_info* loop, pid_t pid) {
free(found);
}
/* Check if SIGCHLD was received, find which PID and reap appropriately */
extern volatile sig_atomic_t received_sigchld;
void sigchld_process(struct loop_info* loop)
typedef struct pid2proto* hash_item;
#include "hash.h"
void remember_child_data(struct loop_info* fd_info,
struct connection* cnx, pid_t pid)
{
int chld;
if (received_sigchld) {
received_sigchld = 0;
do {
chld = waitpid(-1, NULL, WNOHANG);
CHECK_RES_RETURN(chld, "waitpid", );
if (chld) {
decrease_forked_connection(loop, chld);
}
} while (chld);
struct pid2proto* pid2proto = malloc(sizeof(*pid2proto));
pid2proto->pid = pid;
pid2proto->proto = cnx->proto;
pid2proto->endpoint = cnx->endpoint;
if (hash_insert(fd_info->pid2proto, pid2proto)) {
/* TODO something if it fails */
}
}
@@ -170,7 +173,7 @@ void loop_init(struct loop_info* loop)
loop->pid2proto = hash_init(32, pid_make_key, pid_cmp);
if (!loop->pid2proto) {
/* do something! (we're also not doing anything for UDP) */
/* TODO do something! (we're also not doing anything for UDP) */
}
}
+2 -1
View File
@@ -33,7 +33,8 @@ struct connection* cnx_accept_process(struct loop_info* fd_info, struct listen_e
int tidy_connection(struct connection *cnx, struct loop_info* fd_info);
void loop_init(struct loop_info* loop);
void sigchld_process(struct loop_info* loop);
void remember_child_data(struct loop_info* fd_info,
struct connection* cnx, pid_t pid);
/* These must be declared in the loop handler, sslh-ev or sslh-select */
void watchers_add_read(watchers* w, int fd);
+20
View File
@@ -129,6 +129,26 @@ static void cnx_accept_cb(EV_P_ ev_io *w, int revents)
cnx_accept_process(info, gap_get(info->watchers->fd2ls, w->fd));
}
void sigchld_cb(EV_P_ ev_child *w, int revents)
{
printf("sigchld_cb %d\n", w->pid);
struct loop_info* info = ev_userdata(EV_A);
ev_child_stop(EV_A_ w);
decrease_forked_connection(info, w->pid);
free(w);
}
void watcher_sigchld(struct loop_info* fd_info, struct connection* cnx, pid_t pid)
{
ev_child* cw = malloc(sizeof(*cw));
ev_child_init(cw, sigchld_cb, pid, 0);
ev_child_start(EV_DEFAULT_ cw);
}
void main_loop(struct listen_endpoint listen_sockets[], int num_addr_listen)
{
struct loop_info ev_info;
+23
View File
@@ -88,8 +88,31 @@ void watchers_del_write(watchers* w, int fd)
FD_CLR(fd, &w->fds_w);
}
void watcher_sigchld(struct loop_info* fd_info, struct connection* cnx, pid_t pid)
{
/* Nothing to do, watcher is processed in the event loop when select() is
* interrupted by the signal */
}
/* /end watchers */
/* Check if SIGCHLD was received, find which PID and reap appropriately */
extern volatile sig_atomic_t received_sigchld;
static void sigchld_process(struct loop_info* loop)
{
int chld;
printf("sigchld_process\n");
if (received_sigchld) {
received_sigchld = 0;
do {
chld = waitpid(-1, NULL, WNOHANG);
CHECK_RES_RETURN(chld, "waitpid", );
if (chld) {
decrease_forked_connection(loop, chld);
}
} while (chld);
}
}
+4 -9
View File
@@ -26,8 +26,6 @@
#include "log.h"
typedef struct pid2proto* hash_item;
#include "hash.h"
/* Removes cnx from probing list */
static void remove_probing_cnx(struct loop_info* fd_info, struct connection* cnx)
@@ -309,15 +307,12 @@ void fork_shoveling_process(struct loop_info* fd_info, struct connection* cnx) {
case -1: print_message(msg_system_error, "fork failed: err %d: %s\n", errno, strerror(errno));
break;
default: /* parent */
struct pid2proto* pid2proto = malloc(sizeof(*pid2proto));
pid2proto->pid = pid;
pid2proto->proto = cnx->proto;
if (hash_insert(fd_info->pid2proto, pid2proto)) {
/* TODO something if it fails */
}
remember_child_data(fd_info, cnx, pid);
watcher_sigchld(fd_info, cnx, pid);
break;
}
/* Free file descriptor, but do not reduce protocol count */
/* Free file descriptor (used only in child), but do not reduce connection
* counts */
cnx->proto = NULL;
cnx->endpoint = NULL;
tidy_connection(cnx, fd_info);
-8
View File
@@ -5,14 +5,6 @@
#include "collection.h"
#include "tcp-probe.h"
/* Struct to keep track of an association of a forked PID to its
* listening socket and its protocol */
struct pid2proto {
pid_t pid;
struct listen_endpoint* endpoint;
struct sslhcfg_protocols_item* proto;
};
void tcp_read_process(struct loop_info* fd_info, int fd);
struct connection* accept_new_connection(struct listen_endpoint* endpoint, struct loop_info* fd_info);
void probing_read_process(struct connection* cnx, struct loop_info* fd_info);