summaryrefslogtreecommitdiffstats
path: root/alsa-hook
diff options
context:
space:
mode:
authorRonan Le Martret <ronan.lemartret@iot.bzh>2017-11-27 14:19:47 +0100
committerRonan Le Martret <ronan.lemartret@iot.bzh>2017-11-28 09:28:27 +0100
commit2a8b7aeed1b5217a608032ce1afabadd1166e7c3 (patch)
treecc7aba4025643e406e4c40255c06afe473609ac9 /alsa-hook
parent720e487cab65588faf43907b10dd36266b0779a9 (diff)
Improve thread ressource liberation
* afbClient thread must be kill when we Close the alsa Hook Signed-off-by: Ronan Le Martret <ronan.lemartret@iot.bzh> Change-Id: I834f888f41c179950ea7c03d6d9325d7df5b4599
Diffstat (limited to 'alsa-hook')
-rw-r--r--alsa-hook/PolicyAlsaHook.c83
1 files changed, 42 insertions, 41 deletions
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);