[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH (speechd) 3/4] Restructure spd_say, from libspeechd.c.
From: |
Christopher Brannon |
Subject: |
[PATCH (speechd) 3/4] Restructure spd_say, from libspeechd.c. |
Date: |
Fri, 19 Feb 2010 09:50:11 -0600 |
spd_say leaked memory in several places. For instance, it never
freed strings returned by its callees escape_dot and spd_send_data_wo_mutex.
Memory allocated by spd_execute_command_with_reply was freed in the
normal case, but it was leaked in an error case.
I decided to split spd_say into three functions:
spd_say, spd_say_prepare, and spd_say_sending.
The two helper functions are static inline.
spd_say is much simpler, and the multiple return statements are gone.
Next, spd_say calls an auxiliary function named escape_dot. This routine
replaces . with .. when necessary, so that text does not cause the SSIP
message to prematurely terminate.
escape_dot returns NULL in exactly one situation: out-of-memory.
The previous version of spd_say simply sent
the unescaped text to Speech Dispatcher on a failed memory allocation.
After this patch, spd_say fails and returns an error code when
escape_dot fails.
---
src/c/api/libspeechd.c | 126 ++++++++++++++++++++++++++++-------------------
1 files changed, 75 insertions(+), 51 deletions(-)
diff --git a/src/c/api/libspeechd.c b/src/c/api/libspeechd.c
index 56c9b0e..b8274bc 100644
--- a/src/c/api/libspeechd.c
+++ b/src/c/api/libspeechd.c
@@ -307,68 +307,92 @@ spd_close(SPDConnection* connection)
xfree(connection);
}
-/* Say TEXT with priority PRIORITY.
- * Returns msg_uid on success, -1 otherwise. */
-int
-spd_say(SPDConnection *connection, SPDPriority priority, const char* text)
+/* Helper functions for spd_say. */
+static inline int
+spd_say_prepare(SPDConnection *connection, SPDPriority priority,
+ const char* text, char **escaped_text)
{
- static char command[16];
- char *etext;
- int ret;
- char *pret;
- char *reply;
- int err;
- int msg_id;
-
- if (text == NULL) return -1;
-
- pthread_mutex_lock(connection->ssip_mutex);
+ int ret = 0;
SPD_DBG("Text to say is: %s", text);
- /* Set priority */
- SPD_DBG("Setting priority");
- ret = spd_set_priority(connection, priority);
- if(ret) RET(-1);
-
- /* Check if there is no escape sequence in the text */
- etext = escape_dot(text);
- if (etext == NULL) etext = (char*) text;
-
- /* Start the data flow */
- SPD_DBG("Sending SPEAK");
- sprintf(command, "SPEAK");
- ret = spd_execute_command_wo_mutex(connection, command);
- if(ret){
- SPD_DBG("Error: Can't start data flow!");
- RET(-1);
+ /* Insure that there is no escape sequence in the text */
+ *escaped_text = escape_dot(text);
+ /* Caller is now responsible for escaped_text. */
+ if (*escaped_text == NULL) { /* Out of memory. */
+ SPD_DBG("spd_say could not allocate memory.");
+ ret = -1;
+ } else {
+ /* Set priority */
+ SPD_DBG("Setting priority");
+ ret = spd_set_priority(connection, priority);
+ if (!ret) {
+ /* Start the data flow */
+ SPD_DBG("Sending SPEAK");
+ ret = spd_execute_command_wo_mutex(connection, "speak");
+ if (ret) {
+ SPD_DBG("Error: Can't start data flow!");
+ }
+ }
}
-
+
+ return ret;
+}
+
+static inline int
+spd_say_sending(SPDConnection *connection, const char* text)
+{
+ int msg_id = -1;
+ int err = 0;
+ char *reply = NULL;
+ char *pret = NULL;
+
/* Send data */
SPD_DBG("Sending data");
- pret = spd_send_data_wo_mutex(connection, etext, SPD_NO_REPLY);
- if(pret==NULL){
- SPD_DBG("Can't send data wo mutex");
- RET(-1);
- }
-
-
- /* Terminate data flow */
- SPD_DBG("Terminating data flow");
- ret = spd_execute_command_with_reply(connection, "\r\n.", &reply);
- if(ret){
- SPD_DBG("Can't terminate data flow");
- RET(-1);
+ pret = spd_send_data_wo_mutex(connection, text, SPD_NO_REPLY);
+ if (pret==NULL) {
+ SPD_DBG("Can't send data wo mutex");
+ } else {
+ /* Terminate data flow */
+ SPD_DBG("Terminating data flow");
+ err = spd_execute_command_with_reply(connection, "\r\n.", &reply);
+ if (err) {
+ SPD_DBG("Can't terminate data flow");
+ } else {
+ msg_id = get_param_int(reply, 1, &err);
+ if (err < 0) {
+ SPD_DBG("Can't determine SSIP message unique ID parameter.");
+ msg_id = -1;
+ }
+ }
}
- msg_id = get_param_int(reply, 1, &err);
- if (err < 0){
- SPD_DBG("Can't determine SSIP message unique ID parameter.");
- msg_id = -1;
- }
xfree(reply);
+ xfree(pret);
+ return msg_id;
+}
- pthread_mutex_unlock(connection->ssip_mutex);
+/* Say TEXT with priority PRIORITY.
+ * Returns msg_uid on success, -1 otherwise. */
+int
+spd_say(SPDConnection *connection, SPDPriority priority, const char* text)
+{
+ char *escaped_text = NULL;
+ int msg_id = -1;
+ int prepare_failed = 0;
+
+ if (text != NULL) {
+ pthread_mutex_lock(connection->ssip_mutex);
+
+ prepare_failed = spd_say_prepare(connection, priority, text,
&escaped_text);
+ if (!prepare_failed)
+ msg_id = spd_say_sending(connection, escaped_text);
+
+ xfree(escaped_text);
+ pthread_mutex_unlock(connection->ssip_mutex);
+ } else {
+ SPD_DBG("spd_say called with a NULL argument for <text>");
+ }
SPD_DBG("Returning from spd_say");
return msg_id;
--
1.6.6.1