summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJose Bollo <jose.bollo@iot.bzh>2019-08-02 16:23:50 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2019-08-09 14:34:43 +0000
commit6f13ad1989875b5a0ce50b24211fd1fba093735f (patch)
treee88b8447f6b282384ebaa009057c2871db7fb0ff
parent3343b4d0514d25fd1f2365eb25049f748cab688e (diff)
Avoid lock when child dies
Interaction between pthread_cond_wait, pthread_broadcast and signal may lead to lock when the child of afb-daemon dies. To avoid that sad behavior, this commit defers the call to "job_exit" using lazy job queueing. Bug-AGL: SPEC-2720 Change-Id: Ifd1a56f4a439e1704f79a1291fa01f39b1640f29 Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
-rw-r--r--src/afb-session.c2
-rw-r--r--src/main-afb-daemon.c24
2 files changed, 18 insertions, 8 deletions
diff --git a/src/afb-session.c b/src/afb-session.c
index 1bdb59db..61aa3f61 100644
--- a/src/afb-session.c
+++ b/src/afb-session.c
@@ -579,7 +579,7 @@ static int cookeyidx(const void *key)
* @param makecb the creation function or NULL
* @param freecb the release function or NULL
* @param closure an argument for makecb or the value if makecb==NULL
- * @param replace a boolean enforcing replecement of the previous value
+ * @param replace a boolean enforcing replacement of the previous value
*
* @return the value of the cookie
*
diff --git a/src/main-afb-daemon.c b/src/main-afb-daemon.c
index 7b92905f..3421be81 100644
--- a/src/main-afb-daemon.c
+++ b/src/main-afb-daemon.c
@@ -403,15 +403,25 @@ static struct afb_hsrv *start_http_server()
| execute_command
+--------------------------------------------------------- */
-static void wait_child_and_exit()
+static void exit_at_end()
{
+ exit(0);
+}
+
+static void wait_child(int signum, void* arg)
+{
+ pid_t pid = (pid_t)(intptr_t)arg;
pid_t pidchld = childpid;
- childpid = 0;
- if (!SELF_PGROUP)
- killpg(pidchld, SIGKILL);
- waitpid(pidchld, NULL, 0);
- exit(0);
+ if (pidchld == pid) {
+ childpid = 0;
+ if (!SELF_PGROUP)
+ killpg(pidchld, SIGKILL);
+ waitpid(pidchld, NULL, 0);
+ jobs_exit(exit_at_end);
+ } else {
+ waitpid(pid, NULL, 0);
+ }
}
static void on_sigchld(int signum, siginfo_t *info, void *uctx)
@@ -421,7 +431,7 @@ static void on_sigchld(int signum, siginfo_t *info, void *uctx)
case CLD_EXITED:
case CLD_KILLED:
case CLD_DUMPED:
- jobs_exit(wait_child_and_exit);
+ jobs_queue_lazy(0, 0, wait_child, (void*)(intptr_t)info->si_pid);
default:
break;
}