From 2a8b7aeed1b5217a608032ce1afabadd1166e7c3 Mon Sep 17 00:00:00 2001 From: Ronan Le Martret Date: Mon, 27 Nov 2017 14:19:47 +0100 Subject: Improve thread ressource liberation * afbClient thread must be kill when we Close the alsa Hook Signed-off-by: Ronan Le Martret Change-Id: I834f888f41c179950ea7c03d6d9325d7df5b4599 --- alsa-hook/PolicyAlsaHook.c | 83 +++++++++++++++++++++++----------------------- 1 file changed, 42 insertions(+), 41 deletions(-) (limited to 'alsa-hook') diff --git a/alsa-hook/PolicyAlsaHook.c b/alsa-hook/PolicyAlsaHook.c index 146ff5b..db4e5a2 100644 --- a/alsa-hook/PolicyAlsaHook.c +++ b/alsa-hook/PolicyAlsaHook.c @@ -66,7 +66,7 @@ // Currently not implemented #define UNUSED_ARG(x) UNUSED_ ## x __attribute__((__unused__)) - + typedef struct { const char *apiverb; json_object *queryJ; @@ -99,6 +99,7 @@ typedef struct { afbRequestT **request; afbRequestT **release; afbEventT **event; + pthread_t tid; } afbClientT; @@ -142,7 +143,7 @@ void OnEventCB(void *handle, const char *event, int evtid, struct json_object *d afbEventT **afbEvent = afbClient->event; json_object *tmpJ; int signal=0, index; - + // if no event handler just ignore events if (!afbEvent) goto OnErrorExit; @@ -151,18 +152,18 @@ void OnEventCB(void *handle, const char *event, int evtid, struct json_object *d // loop on event/signal mapping table for (index=0; afbEvent[index]!= NULL; index++) { int done; - + done = json_object_object_get_ex(dataJ,afbEvent[index]->search, &tmpJ); if (done) { - + if (afbEvent[index]->value) { // search value is a string if (json_object_get_type(tmpJ) != json_type_string) goto OnErrorExit; const char *value=json_object_get_string(tmpJ); if (!strcmp(afbEvent[index]->value, value)) signal=afbEvent[index]->signal; - + } else { - + // search value is an integer if (json_object_get_type(tmpJ) != json_type_int) goto OnErrorExit; int ivalue=json_object_get_int(tmpJ); @@ -176,7 +177,7 @@ void OnEventCB(void *handle, const char *event, int evtid, struct json_object *d if (afbClient->verbose) printf("ON-EVENT self-signal search=%s signal=%d\n", afbEvent[index]->search, afbEvent[index]->signal); if (afbEvent[index]->signal) kill (getpid(), afbEvent[index]->signal); } - + return; OnErrorExit: @@ -185,7 +186,7 @@ OnErrorExit: } static void OnSuccessCB(void* UNUSED_ARG(ctx) , void* handle, json_object* responseJ, const char* info) { - + afbRequestT *afbRequest= (afbRequestT*)handle; afbClientT *afbClient=(afbClientT*)afbRequest->afbClient; @@ -194,7 +195,7 @@ static void OnSuccessCB(void* UNUSED_ARG(ctx) , void* handle, json_object* respo // Cancel timeout for this request sd_event_source_unref(afbRequest->evtSource); free(afbRequest->callIdTag); - + // When not more waiting call release semaphore afbClient->count--; if (afbClient->synchronous) { @@ -207,7 +208,7 @@ static void OnSuccessCB(void* UNUSED_ARG(ctx) , void* handle, json_object* respo } static void OnFailureCB(void* UNUSED_ARG(ctx), void* handle, const char *status, const char *info) { - + afbRequestT *afbRequest= (afbRequestT*)handle; afbClientT *afbClient=(afbClientT*)afbRequest->afbClient; @@ -263,13 +264,13 @@ static int CallWithTimeout(afbClientT *afbClient, afbRequestT *afbRequest, int c if (afbRequest->apiverb) { if (afbClient->verbose) printf("CALL-REQUEST verb=%s query=%s tag=%s session=%s\n", afbRequest->apiverb, json_object_get_string(afbRequest->queryJ), afbRequest->callIdTag, afbClient->uid); err = afb_proto_ws_client_call(afbClient->pws, afbRequest->apiverb, afbRequest->queryJ, afbClient->uid, afbRequest); - if (err < 0 ) goto OnErrorExit; + if (err < 0 ) goto OnErrorExit; } - + // save client handle in request - afbRequest->afbClient = afbClient; + afbRequest->afbClient = afbClient; afbClient->count ++; - + // in synchronous mode we wait for CB to return if (afbClient->synchronous) { sem_wait(&afbClient->semaphore); @@ -284,14 +285,12 @@ OnErrorExit: } static int LaunchCallRequest(afbClientT *afbClient, hookActionT action) { - - pthread_t tid; int err, idx; // each callback on error add one to error count. - + afbClient->errcount = 0; - + switch (action) { case HOOK_INSTALL: { @@ -308,7 +307,7 @@ static int LaunchCallRequest(afbClientT *afbClient, hookActionT action) { } // start a thread with a mainloop to monitor Audio-Agent - err = pthread_create(&tid, NULL, &LoopInThread, afbClient); + err = pthread_create(&afbClient->tid, NULL, &LoopInThread, afbClient); if (err) goto OnErrorExit; afbClient->pws = afb_ws_client_connect_api(afbClient->sdLoop, afbClient->uri, &itf, afbClient); @@ -327,19 +326,19 @@ static int LaunchCallRequest(afbClientT *afbClient, hookActionT action) { fprintf(stderr, "LaunchCallRequest: HOOK_INSTALL:fatal mandatory request call missing in asoundrc\n"); goto OnErrorExit;; } - + // send call request to audio-agent asynchronously (respond with thread mainloop context) for (idx = 0; afbClient->request[idx] != NULL; idx++) { err = CallWithTimeout(afbClient, afbClient->request[idx], idx); if (err) goto OnErrorExit; } // launch counter to keep track of waiting request call - afbClient->count=idx; + afbClient->count=idx; break; } - + case HOOK_CLOSE: { - + // If no request exit now if (!afbClient->release) { if (afbClient->verbose) printf("LaunchCallRequest:optional HOOK_CLOSE no release control call\n"); @@ -352,15 +351,15 @@ static int LaunchCallRequest(afbClientT *afbClient, hookActionT action) { if (err) goto OnErrorExit; } // launch counter to keep track of waiting request call - afbClient->count=idx; + afbClient->count=idx; break; } - + default: - fprintf(stderr, "LaunchCallRequest (hoops): Unknown action"); + fprintf(stderr, "LaunchCallRequest (hoops): Unknown action"); goto OnErrorExit; } - + return 0; OnErrorExit: @@ -385,6 +384,8 @@ static int AlsaCloseHook(snd_pcm_hook_t *hook) { goto OnErrorExit; } + pthread_cancel(afbClient->tid); + if (afbClient->verbose) fprintf(stdout, "\nAlsaHook Close Success PCM=%s URI=%s\n", snd_pcm_name(afbClient->pcm), afbClient->uri); return 0; @@ -395,11 +396,11 @@ OnErrorExit: // Get an asoundrc compound and return it as a JSON object static json_object* AlsaGetJson (snd_config_t *ctlconfig, const char *id, const char*label) { - + json_object *queryJ; snd_config_type_t ctype; char* query; - + // each control is a sting that contain a json object ctype = snd_config_get_type(ctlconfig); snd_config_get_string(ctlconfig, (const char**) &query); @@ -417,9 +418,9 @@ static json_object* AlsaGetJson (snd_config_t *ctlconfig, const char *id, const SNDERR("Not a valid Json object control='%s' query='%s'", id, query); goto OnErrorExit; } - + return queryJ; - + OnErrorExit: return NULL; } @@ -459,7 +460,7 @@ static int AlsaGetActions (snd_config_t *node, afbRequestT **afbRequest, const c } afbRequest[callCount]=NULL; // afbEvent array is NULL terminated } - + return 0; OnErrorExit: @@ -523,7 +524,7 @@ static int AlsaGetEvents (snd_config_t *node, afbEventT **afbEvent, const char*i afbEvent[callCount]->search=strdup(search); } else { SNDERR("Missing 'search' from event/signal 'search' from signal definition %s", confEvents); - goto OnErrorExit; + goto OnErrorExit; } // pattern should have a value @@ -534,7 +535,7 @@ static int AlsaGetEvents (snd_config_t *node, afbEventT **afbEvent, const char*i case SND_CONFIG_TYPE_INTEGER: snd_config_get_integer(itemConf, &afbEvent[callCount]->ivalue); break; - + case SND_CONFIG_TYPE_STRING: snd_config_get_string(itemConf, &value); afbEvent[callCount]->value=strdup(value); @@ -545,7 +546,7 @@ static int AlsaGetEvents (snd_config_t *node, afbEventT **afbEvent, const char*i } } else { SNDERR("Missing 'value' from event/signal 'value' from signal definition %s", confEvents); - goto OnErrorExit; + goto OnErrorExit; } // move to next call if any @@ -575,7 +576,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) { afbClient->verbose = 0; (void) asprintf(&afbClient->uid, "alsa-hook-pid:%d", getpid()); - + // Get PCM arguments from asoundrc snd_config_for_each(it, next, conf) { snd_config_t *node = snd_config_iterator_entry(it); @@ -603,7 +604,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) { } continue; } - + if (strcmp(id, "synchronous") == 0) { afbClient->synchronous= snd_config_get_bool(node); if (afbClient->synchronous < 0) { @@ -612,7 +613,7 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) { } continue; } - + if (strcmp(id, "timeout") == 0) { if (snd_config_get_integer(node, &afbClient->timeout) < 0) { SNDERR("Invalid timeout Integer %s", id); @@ -620,21 +621,21 @@ int PLUGIN_ENTRY_POINT (snd_pcm_t *pcm, snd_config_t *conf) { } continue; } - + if (strcmp(id, "request") == 0) { afbClient->request = malloc(MAX_API_CALL * sizeof(afbRequestT*));; int err= AlsaGetActions(node, afbClient->request , id); if (err) goto OnErrorExit; continue; } - + if (strcmp(id, "release") == 0) { afbClient->release = malloc(MAX_API_CALL * sizeof(afbRequestT*));; int err= AlsaGetActions(node, afbClient->release, id); if (err) goto OnErrorExit; continue; } - + if (strcmp(id, "events") == 0) { afbClient->event= malloc(MAX_API_CALL * sizeof(afbRequestT*));; int err= AlsaGetEvents(node, afbClient->event, id); -- cgit 1.2.3-korg