feat: add address sanitizer, persistent FIFO fds, and latency test

This commit is contained in:
Loic Coenen
2026-05-24 09:22:22 +00:00
committed by Loic Coenen (aider)
parent 0537263a7a
commit dd67576c45
6 changed files with 217 additions and 69 deletions

View File

@@ -1,5 +1,5 @@
CC = gcc
CFLAGS = -Wall -Wextra -Wpedantic -std=c11 -Isrc -I../engine/src
CFLAGS = -Wall -Wextra -Wpedantic -std=c11 -Isrc -I../engine/src -fsanitize=address -fno-omit-frame-pointer
CARLA_INC = -I/usr/include/carla -I/usr/include/carla/includes
CARLA_LIB = -L/usr/lib/carla -Wl,-rpath,/usr/lib/carla -lcarla_standalone2
@@ -20,10 +20,10 @@ TEST_INTEGRATION_BIN = test_integration
all: looper-client test_status_parse
looper-client: src/main.c src/tui.c $(PLUGINS_OBJ) $(CARLA_OBJ) $(CLIENT_CMD_OBJ) $(SCRIPT_OBJ) $(LOG_OBJ)
$(CC) $(CFLAGS) $(CARLA_INC) -o $@ $^ $(CARLA_LIB) -ljack -lncurses
$(CC) $(CFLAGS) $(CARLA_INC) -fsanitize=address -o $@ $^ $(CARLA_LIB) -ljack -lncurses
test_status_parse: tests/test_status_parse.c $(PLUGINS_OBJ) $(CARLA_OBJ) $(CLIENT_CMD_OBJ) $(SCRIPT_OBJ)
$(CC) $(CFLAGS) $(CARLA_INC) -o test_status_parse tests/test_status_parse.c src/tui.c $(PLUGINS_OBJ) $(CARLA_OBJ) $(CLIENT_CMD_OBJ) $(SCRIPT_OBJ) $(CARLA_LIB) -ljack -lncurses
test_status_parse: tests/test_status_parse.c $(PLUGINS_OBJ) $(CARLA_OBJ) $(CLIENT_CMD_OBJ) $(SCRIPT_OBJ) $(LOG_OBJ)
$(CC) $(CFLAGS) $(CARLA_INC) -o test_status_parse tests/test_status_parse.c src/tui.c $(PLUGINS_OBJ) $(CARLA_OBJ) $(CLIENT_CMD_OBJ) $(SCRIPT_OBJ) $(LOG_OBJ) $(CARLA_LIB) -ljack -lncurses
# --- Plugin stubs (now real) ---
$(PLUGINS_OBJ): src/plugins.c src/plugins.h
@@ -84,7 +84,7 @@ TEST_CLIENT_OBJ = tests/test_client.o
$(TEST_CLIENT_OBJ): tests/test_client.c src/tui.h
$(CC) $(CFLAGS) $(CARLA_INC) -c -o $@ $<
$(TEST_CLIENT_BIN): $(TEST_CLIENT_OBJ) src/tui.c $(PLUGINS_OBJ) $(CARLA_OBJ) $(CLIENT_CMD_OBJ) $(SCRIPT_OBJ)
$(TEST_CLIENT_BIN): $(TEST_CLIENT_OBJ) src/tui.c $(PLUGINS_OBJ) $(CARLA_OBJ) $(CLIENT_CMD_OBJ) $(SCRIPT_OBJ) $(LOG_OBJ)
$(CC) $(CFLAGS) $(CARLA_INC) -o $@ $^ $(CARLA_LIB) -ljack -lncurses
# --- Carla host tests ---

View File

@@ -1,5 +1,6 @@
#include <CarlaHost.h>
#include <CarlaBackend.h>
#include <stdio.h>
#include <string.h>
#include "carla_host.h"
@@ -137,21 +138,25 @@ int carla_connect(int id, const char *port_name, const char *looper_port) {
if (!port_name || !looper_port) return -1;
if (!jack_client) return -1;
fprintf(stderr, "CARLA_CONNECT: plugin_id=%d conn_count=%d port=%s looper=%s\n",
id, conn_count, port_name, looper_port);
// Real JACK port connection
int ret = jack_connect(jack_client, looper_port, port_name);
if (ret != 0) return -1;
// Store the connection so we can disconnect it later
if (conn_count < MAX_CONNECTIONS) {
connections[conn_count].plugin_id = id;
strncpy(connections[conn_count].plugin_port, port_name,
sizeof(connections[conn_count].plugin_port) - 1);
connections[conn_count].plugin_port[sizeof(connections[conn_count].plugin_port) - 1] = '\0';
strncpy(connections[conn_count].looper_port, looper_port,
sizeof(connections[conn_count].looper_port) - 1);
connections[conn_count].looper_port[sizeof(connections[conn_count].looper_port) - 1] = '\0';
conn_count++;
if (conn_count >= MAX_CONNECTIONS) {
fprintf(stderr, "WARN: connection array full, refusing new connection\n");
return -1;
}
connections[conn_count].plugin_id = id;
strncpy(connections[conn_count].plugin_port, port_name,
sizeof(connections[conn_count].plugin_port) - 1);
connections[conn_count].plugin_port[sizeof(connections[conn_count].plugin_port) - 1] = '\0';
strncpy(connections[conn_count].looper_port, looper_port,
sizeof(connections[conn_count].looper_port) - 1);
connections[conn_count].looper_port[sizeof(connections[conn_count].looper_port) - 1] = '\0';
conn_count++;
return 0;
}

View File

@@ -24,34 +24,29 @@
static bool engine_running = false;
static bool debug_mode = false;
/* Persistent FIFO fds open once and reuse */
static int cmd_fifo_fd = -1;
static int status_fifo_fd = -1;
/* ---------- FIFO command helper ---------- */
int send_command(const char *cmd) {
if (debug_mode)
fprintf(stderr, "DEBUG: send_command(%s)\n", cmd);
const char *fifo_path = getenv("LOOPER_CMD_FIFO");
if (!fifo_path) fifo_path = "/tmp/looper_cmd";
// Retry open up to 5 times with a short sleep, blocking mode
int fd = -1;
for (int attempt = 0; attempt < 5 && fd < 0; attempt++) {
fd = open(fifo_path, O_WRONLY); // blocking waits for reader
if (fd < 0) {
if (errno == ENXIO && attempt < 4)
{
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
nanosleep(&ts, NULL);
}
else
break;
if (cmd_fifo_fd < 0) {
const char *fifo_path = getenv("LOOPER_CMD_FIFO");
if (!fifo_path) fifo_path = "/tmp/looper_cmd";
cmd_fifo_fd = open(fifo_path, O_WRONLY);
if (cmd_fifo_fd < 0) {
perror("open cmd FIFO");
return -1;
}
}
if (fd < 0) return -1;
size_t len = strlen(cmd);
int n = write(fd, cmd, len);
int n = write(cmd_fifo_fd, cmd, len);
if (n == (int)len && cmd[len-1] != '\n')
write(fd, "\n", 1);
close(fd);
write(cmd_fifo_fd, "\n", 1);
return (n >= 0) ? 0 : -1;
}
@@ -254,10 +249,12 @@ static bool in_colon = false;
/* Read the status FIFO once and update cell_state array */
static void tui_read_status(void) {
int fd = open(STATUS_FIFO, O_RDONLY | O_NONBLOCK);
if (fd < 0) return;
char buf[256];
int n = read(fd, buf, sizeof(buf)-1);
if (status_fifo_fd < 0) {
status_fifo_fd = open(STATUS_FIFO, O_RDONLY | O_NONBLOCK);
if (status_fifo_fd < 0) return;
}
char buf[4096];
int n = read(status_fifo_fd, buf, sizeof(buf)-1);
if (n > 0) {
buf[n] = '\0';
char *line = buf;
@@ -274,7 +271,7 @@ static void tui_read_status(void) {
if (nl) { *nl = '\n'; line = nl + 1; } else break;
}
}
close(fd);
/* keep fd open */
}
void tui_run(void) {
@@ -310,7 +307,14 @@ void tui_run(void) {
}
/* redraw grid (status may have changed no extra key needed) */
draw_grid();
{
struct timespec t1, t2;
clock_gettime(CLOCK_MONOTONIC, &t1);
draw_grid();
clock_gettime(CLOCK_MONOTONIC, &t2);
double ms = (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_nsec - t1.tv_nsec)/1000000.0;
if (ms > 200) log_msg("SLOW draw_grid: %f ms", ms);
}
int chc = getch();
@@ -470,6 +474,14 @@ void tui_run(void) {
}
void tui_cleanup(void) {
if (cmd_fifo_fd >= 0) {
close(cmd_fifo_fd);
cmd_fifo_fd = -1;
}
if (status_fifo_fd >= 0) {
close(status_fifo_fd);
status_fifo_fd = -1;
}
if (yank_buffer.clip_indices) free(yank_buffer.clip_indices);
/* free script note allocations */
script_cleanup();