summaryrefslogblamecommitdiff
path: root/user/speech-dispatcher/threadleak.patch
blob: 6983a6dabf96c7aec864703cb4181fdbb68cf080 (plain) (tree)



















































































                                                                                                     
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;