fix: prevent hang in scene add/remove test and fix unsafe scene copy
Co-authored-by: aider (deepseek/deepseek-reasoner) <aider@aider.chat>
This commit is contained in:
@@ -91,9 +91,18 @@ void channel_remove_scene(jack_client_t *client, int idx) {
|
||||
if (cur[idx].scene_count <= 1)
|
||||
return;
|
||||
int cs = cur[idx].current_scene;
|
||||
/* shift remaining scenes down */
|
||||
/* shift remaining scenes down (safe copy of fields) */
|
||||
for (int i = cs; i < cur[idx].scene_count - 1; i++) {
|
||||
cur[idx].scenes[i] = cur[idx].scenes[i + 1];
|
||||
cur[idx].scenes[i].loop_count = cur[idx].scenes[i+1].loop_count;
|
||||
cur[idx].scenes[i].record_pos = cur[idx].scenes[i+1].record_pos;
|
||||
cur[idx].scenes[i].playback_pos = cur[idx].scenes[i+1].playback_pos;
|
||||
atomic_store(&cur[idx].scenes[i].state,
|
||||
atomic_load(&cur[idx].scenes[i+1].state));
|
||||
cur[idx].scenes[i].prev_state = cur[idx].scenes[i+1].prev_state;
|
||||
/* copy loop data */
|
||||
memcpy(cur[idx].scenes[i].loop.audio_buffer,
|
||||
cur[idx].scenes[i+1].loop.audio_buffer,
|
||||
LOOP_BUF_SIZE * sizeof(float));
|
||||
}
|
||||
cur[idx].scene_count--;
|
||||
if (cur[idx].current_scene >= cur[idx].scene_count)
|
||||
|
||||
@@ -1135,34 +1135,79 @@ static int write_fifo(const char *cmd) {
|
||||
|
||||
static int test_scene_add_remove(void) {
|
||||
printf("Test: scene add/remove via FIFO\n");
|
||||
fflush(stdout);
|
||||
pid_t pid = start_looper();
|
||||
if (pid < 0) return 1;
|
||||
|
||||
/* add a scene */
|
||||
printf(" sending scene_add...\n");
|
||||
fflush(stdout);
|
||||
if (!write_fifo("scene_add\n")) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
kill(pid, SIGTERM);
|
||||
for (int tries = 0; tries < 20; tries++) {
|
||||
int wstatus;
|
||||
pid_t ret = waitpid(pid, &wstatus, WNOHANG);
|
||||
if (ret == pid) break;
|
||||
if (ret < 0) break;
|
||||
safe_usleep(100000);
|
||||
}
|
||||
kill(pid, SIGKILL); waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: cannot write to FIFO\n");
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(50000); /* allow processing */
|
||||
|
||||
/* verify that scene_next works (doesn't crash) */
|
||||
printf(" sending scene_next...\n");
|
||||
fflush(stdout);
|
||||
if (!write_fifo("scene_next\n")) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
kill(pid, SIGTERM);
|
||||
for (int tries = 0; tries < 20; tries++) {
|
||||
int wstatus;
|
||||
pid_t ret = waitpid(pid, &wstatus, WNOHANG);
|
||||
if (ret == pid) break;
|
||||
if (ret < 0) break;
|
||||
safe_usleep(100000);
|
||||
}
|
||||
kill(pid, SIGKILL); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(50000);
|
||||
|
||||
/* remove scene */
|
||||
printf(" sending scene_remove...\n");
|
||||
fflush(stdout);
|
||||
if (!write_fifo("scene_remove\n")) {
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
kill(pid, SIGTERM);
|
||||
for (int tries = 0; tries < 20; tries++) {
|
||||
int wstatus;
|
||||
pid_t ret = waitpid(pid, &wstatus, WNOHANG);
|
||||
if (ret == pid) break;
|
||||
if (ret < 0) break;
|
||||
safe_usleep(100000);
|
||||
}
|
||||
kill(pid, SIGKILL); waitpid(pid, NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
safe_usleep(50000);
|
||||
|
||||
kill(pid, SIGTERM); waitpid(pid, NULL, 0);
|
||||
printf(" PASS (no crash means success)\n");
|
||||
/* kill with timeout */
|
||||
kill(pid, SIGTERM);
|
||||
for (int tries = 0; tries < 20; tries++) {
|
||||
int wstatus;
|
||||
pid_t ret = waitpid(pid, &wstatus, WNOHANG);
|
||||
if (ret == pid) {
|
||||
printf(" PASS (scene add/remove, looper exited)\n");
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
if (ret < 0) {
|
||||
perror("waitpid");
|
||||
break;
|
||||
}
|
||||
safe_usleep(100000); /* 100ms */
|
||||
}
|
||||
kill(pid, SIGKILL);
|
||||
waitpid(pid, NULL, 0);
|
||||
fprintf(stderr, " FAIL: looper did not exit in time\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_scene_next_prev_midi(void) {
|
||||
|
||||
Reference in New Issue
Block a user