]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
v4: Amend async exec calls to ensure both child process exited and fd callbacks have...
authorNick Porter <nick@portercomputing.co.uk>
Tue, 15 Jun 2021 21:24:28 +0000 (22:24 +0100)
committerGitHub <noreply@github.com>
Tue, 15 Jun 2021 21:24:28 +0000 (16:24 -0500)
* Improve debug message - program has exited, not necessarily failed

* Report all output from exec

* Only resume unlang execution when both the child process has...

... exited and the fd event has seen an EOF

src/lib/server/exec.c
src/modules/rlm_exec/rlm_exec.c

index 35c93573ad04a67e6208c557e892ba0cece7e232..cf0f3b454f211b64a73208048f1b7fbf5f5d202f 100644 (file)
@@ -932,7 +932,7 @@ static void exec_waitpid(UNUSED fr_event_list_t *el, UNUSED pid_t pid, int statu
        request_t       *request = exec->request;
 
        if (WIFEXITED(status)) {
-               RDEBUG("Program failed with status code %d", WEXITSTATUS(status));
+               RDEBUG("Program exited with status code %d", WEXITSTATUS(status));
                exec->status = WEXITSTATUS(status);
        } else if (WIFSIGNALED(status)) {
                RDEBUG("Program exited due to signal with status code %d", WTERMSIG(status));
@@ -948,6 +948,10 @@ static void exec_waitpid(UNUSED fr_event_list_t *el, UNUSED pid_t pid, int statu
         *      "pipe has been closed" signal
         */
        if (exec->stdout_fd >= 0) {
+               if (exec->stdout_used) {
+                       RDEBUG("Program exited without EOF being read");
+                       return;
+               }
                (void) fr_event_fd_delete(exec->request->el, exec->stdout_fd, FR_EVENT_FILTER_IO);
                close(exec->stdout_fd);
                exec->stdout_fd = -1;
@@ -1001,7 +1005,7 @@ static void exec_timeout(
 /*
  *     Callback to read stdout from an exec into the pre-prepared extensible sbuff
  */
-static void exec_stdout_read(UNUSED fr_event_list_t *el, int fd, UNUSED int flags, void *uctx) {
+static void exec_stdout_read(UNUSED fr_event_list_t *el, int fd, int flags, void *uctx) {
        fr_exec_state_t         *exec = uctx;
        request_t               *request = exec->request;
        ssize_t                 data_len, remaining;
@@ -1046,6 +1050,24 @@ static void exec_stdout_read(UNUSED fr_event_list_t *el, int fd, UNUSED int flag
                fr_sbuff_advance(&exec->stdout_buff, data_len);
        } while (remaining == data_len);        /* If process returned maximum output, loop again */
 
+       if (flags & EV_EOF) {
+               /*
+                *      We've received EOF - so the process has finished writing
+                *      Remove event and tidy up
+                */
+               (void) fr_event_fd_delete(exec->request->el, fd, FR_EVENT_FILTER_IO);
+               close(fd);
+               exec->stdout_fd = -1;
+
+               if (exec->pid == 0) {
+                       /*
+                        *      Child has already exited - unlang can resume
+                        */
+                       if (exec->ev) fr_event_timer_delete(&exec->ev);
+                       unlang_interpret_mark_runnable(exec->request);
+               }
+       }
+
        /*
         *      Only print if we got additional data
         */
index 7a7081c21480b1b7f2eee5214e70fe5e2cb05e0d..b63c09d29546ca4005178b0da37096dda92b93de 100644 (file)
@@ -379,7 +379,7 @@ static unlang_action_t mod_exec_wait_resume(rlm_rcode_t *p_result, module_ctx_t
                fr_pair_list_t vps, *output_pairs;
                fr_value_box_t *box = fr_dlist_head(&m->box);
 
-               RDEBUG("EXEC GOT -- %pV", box);
+               RDEBUG("EXEC GOT -- %pM", &m->box);
 
                fr_pair_list_init(&vps);
                output_pairs = tmpl_list_head(request, inst->output_list);