Add the ability to retrieve the exit code of the forked AGI process. If there
[asterisk/asterisk.git] / res / res_agi.c
index 481edc5..7c7e5ce 100644 (file)
@@ -39,6 +39,7 @@
 #include <stdio.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <sys/wait.h>
 
 #include "asterisk.h"
 
@@ -275,9 +276,11 @@ static enum agi_result launch_script(char *script, char *argv[], int *fds, int *
                        return AGI_RESULT_FAILURE;
                }
        }
+       ast_replace_sigchld();
        pid = fork();
        if (pid < 0) {
                ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
+               ast_unreplace_sigchld();
                return AGI_RESULT_FAILURE;
        }
        if (!pid) {
@@ -1781,7 +1784,7 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf)
        return 0;
 }
 #define RETRY  3
-static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int dead)
+static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead)
 {
        struct ast_channel *c;
        int outfd;
@@ -1830,6 +1833,7 @@ static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi
                                        returnstatus = -1;
                                if (option_verbose > 2) 
                                        ast_verbose(VERBOSE_PREFIX_3 "AGI Script %s completed, returning %d\n", request, returnstatus);
+                               waitpid(pid, status, 0);
                                /* No need to kill the pid anymore, since they closed us */
                                pid = -1;
                                break;
@@ -1976,13 +1980,18 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
 #endif
        res = launch_script(argv[0], argv, fds, enhanced ? &efd : NULL, &pid);
        if (res == AGI_RESULT_SUCCESS) {
+               int status = 0;
                agi.fd = fds[1];
                agi.ctrl = fds[0];
                agi.audio = efd;
-               res = run_agi(chan, argv[0], &agi, pid, dead);
+               res = run_agi(chan, argv[0], &agi, pid, &status, dead);
+               /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
+               if (res == AGI_RESULT_SUCCESS && status)
+                       res = AGI_RESULT_FAILURE;
                close(fds[1]);
                if (efd > -1)
                        close(efd);
+               ast_unreplace_sigchld();
        }
        ast_localuser_remove(me, u);