Skip to content

Commit 62df177

Browse files
piSaneBow
pi
authored andcommitted
Fix termination on consumer disconnect
When the consumer (aka reader of the out fifo pipe) closes the fifo, the next write to it will cause a SIGPIPE and the ec process terminates with exit code 141. To prevent this, make the process ignore the SIGPIPE signal. This is fine as that is the only place where ec writes to a fifo, and allows the error to be handled locally instead of in a global signal handler. In case a write fails because of a broken pipe, close the fd and re-open it. This will then again block until a consumer connects, and write to it when it does. Fixes voice-engine#13
1 parent e60004b commit 62df177

File tree

2 files changed

+32
-19
lines changed

2 files changed

+32
-19
lines changed

src/ec.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ int main(int argc, char *argv[])
203203
sigemptyset(&sig_int_handler.sa_mask);
204204
sig_int_handler.sa_flags = 0;
205205
sigaction(SIGINT, &sig_int_handler, NULL);
206+
sig_int_handler.sa_handler = SIG_IGN;
207+
sigaction(SIGPIPE, &sig_int_handler, NULL);
206208

207209
echo_state = speex_echo_state_init_mc(frame_size,
208210
config.filter_length,

src/fifo.c

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <sys/stat.h>
77
#include <unistd.h>
88
#include <pthread.h>
9+
#include <errno.h>
910

1011
#include "pa_ringbuffer.h"
1112
#include "conf.h"
@@ -20,32 +21,42 @@ void *fifo_thread(void *ptr)
2021
conf_t *conf = (conf_t *)ptr;
2122
ring_buffer_size_t size1, size2, available;
2223
void *data1, *data2;
23-
int fd = open(conf->out_fifo, O_WRONLY); // will block until reader is available
24-
if (fd < 0) {
25-
printf("failed to open %s, error %d\n", conf->out_fifo, fd);
26-
return NULL;
27-
}
2824

29-
// clear
30-
PaUtil_AdvanceRingBufferReadIndex(&g_out_ringbuffer, PaUtil_GetRingBufferReadAvailable(&g_out_ringbuffer));
3125
while (!g_is_quit)
3226
{
33-
available = PaUtil_GetRingBufferReadAvailable(&g_out_ringbuffer);
34-
PaUtil_GetRingBufferReadRegions(&g_out_ringbuffer, available, &data1, &size1, &data2, &size2);
35-
if (size1 > 0) {
36-
int result = write(fd, data1, size1 * g_out_ringbuffer.elementSizeBytes);
37-
// printf("write %d of %d\n", result / 2, size1);
38-
if (result > 0) {
39-
PaUtil_AdvanceRingBufferReadIndex(&g_out_ringbuffer, result / g_out_ringbuffer.elementSizeBytes);
27+
int fd = open(conf->out_fifo, O_WRONLY); // will block until reader is available
28+
if (fd < 0) {
29+
printf("failed to open %s, error %d\n", conf->out_fifo, fd);
30+
return NULL;
31+
} else {
32+
printf("Microphone-Consumer connected\n");
33+
}
34+
35+
// clear
36+
PaUtil_AdvanceRingBufferReadIndex(&g_out_ringbuffer, PaUtil_GetRingBufferReadAvailable(&g_out_ringbuffer));
37+
while (!g_is_quit)
38+
{
39+
available = PaUtil_GetRingBufferReadAvailable(&g_out_ringbuffer);
40+
PaUtil_GetRingBufferReadRegions(&g_out_ringbuffer, available, &data1, &size1, &data2, &size2);
41+
if (size1 > 0) {
42+
errno = 0;
43+
int result = write(fd, data1, size1 * g_out_ringbuffer.elementSizeBytes);
44+
//printf("write %d of %ld\n", result / 2, size1);
45+
if (result > 0) {
46+
PaUtil_AdvanceRingBufferReadIndex(&g_out_ringbuffer, result / g_out_ringbuffer.elementSizeBytes);
47+
} else if (result < 0 && errno == EPIPE) {
48+
printf("Microphone-Consumer disconnected\n");
49+
break;
50+
} else {
51+
sleep(1);
52+
}
4053
} else {
41-
sleep(1);
54+
usleep(100000);
4255
}
43-
} else {
44-
usleep(100000);
4556
}
46-
}
4757

48-
close(fd);
58+
close(fd);
59+
}
4960

5061
return NULL;
5162
}

0 commit comments

Comments
 (0)