From a054e9469dd6481e24c385162013fc14fefb940f Mon Sep 17 00:00:00 2001
From: Samuel Thibault <samuel.thibault@ens-lyon.org>
Date: Sun, 13 Mar 2022 17:04:09 +0100
Subject: [PATCH] libspeechd: Fix memleak when using threaded mode
---
src/api/c/libspeechd.c | 36 ++++++++++++++++++++++++++----------
1 file changed, 26 insertions(+), 10 deletions(-)
diff --git a/src/api/c/libspeechd.c b/src/api/c/libspeechd.c
index b0f30286..dd4c7f7b 100644
--- a/src/api/c/libspeechd.c
+++ b/src/api/c/libspeechd.c
@@ -1777,21 +1777,35 @@ static int spd_set_priority(SPDConnection * connection, SPDPriority priority)
return spd_execute_command_wo_mutex(connection, command);
}
+struct get_reply_data {
+ GString *str;
+ char *line;
+};
+
+static void get_reply_cleanup(void *arg)
+{
+ struct get_reply_data *data = arg;
+ g_string_free(data->str, TRUE);
+ free(data->line);
+}
+
static char *get_reply(SPDConnection * connection)
{
- GString *str;
- char *line = NULL;
size_t N = 0;
int bytes;
char *reply;
gboolean errors = FALSE;
+ struct get_reply_data data;
- str = g_string_new("");
+ data.line = NULL;
+ data.str = g_string_new("");
+
+ pthread_cleanup_push(get_reply_cleanup, &data);
/* Wait for activity on the socket, when there is some,
read all the message line by line */
do {
- bytes = getline(&line, &N, connection->stream);
+ bytes = getline(&data.line, &N, connection->stream);
if (bytes == -1) {
SPD_DBG
("Error: Can't read reply, broken socket in get_reply!");
@@ -1800,22 +1814,24 @@ static char *get_reply(SPDConnection * connection)
connection->stream = NULL;
errors = TRUE;
} else {
- g_string_append(str, line);
+ g_string_append(data.str, data.line);
}
/* terminate if we reached the last line (without '-' after numcode) */
- } while (!errors && !((strlen(line) < 4) || (line[3] == ' ')));
+ } while (!errors && !((strlen(data.line) < 4) || (data.line[3] == ' ')));
+
+ pthread_cleanup_pop(0);
- free(line); /* getline allocates with malloc. */
+ free(data.line); /* getline allocates with malloc. */
if (errors) {
/* Free the GString and its character data, and return NULL. */
- g_string_free(str, TRUE);
+ g_string_free(data.str, TRUE);
reply = NULL;
} else {
/* The resulting message received from the socket is stored in reply */
- reply = str->str;
+ reply = data.str->str;
/* Free the GString, but not its character data. */
- g_string_free(str, FALSE);
+ g_string_free(data.str, FALSE);
}
return reply;