From: Radosław Korzeniewski Date: Tue, 26 Oct 2021 17:11:43 +0000 (+0200) Subject: pluginlib: Update execprog to better handle termination. X-Git-Tag: Beta-15.0.0~786 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=09aee3065b8311c41043ee555adf73e3665d5b4f;p=thirdparty%2Fbacula.git pluginlib: Update execprog to better handle termination. --- diff --git a/bacula/src/plugins/fd/pluginlib/execprog.cpp b/bacula/src/plugins/fd/pluginlib/execprog.cpp index 8d4c8fb52..74e629cef 100644 --- a/bacula/src/plugins/fd/pluginlib/execprog.cpp +++ b/bacula/src/plugins/fd/pluginlib/execprog.cpp @@ -31,6 +31,7 @@ /* Plugin compile time variables */ #define PLUGINPREFIX "execprog:" + /* * Terminate the connection represented by BPIPE object. * it shows a debug and job messages when connection close is unsuccessful @@ -42,31 +43,43 @@ * out: * none */ -void EXECPROG::terminate(bpContext *ctx, bool raise_error) +int EXECPROG::terminate(bpContext *ctx, bool raise_error) { - if (is_closed()) - { - return; - } + // clear status + tstatus = 0; + pm_strcpy(m_errmsg, NULL); - // after close_bpipe it is no longer available - tstatus = close_bpipe(bpipe); - if (tstatus && raise_error) + if (!is_closed()) { - /* error during close */ + // after close_bpipe it is no longer available + pid_t wpid = bpipe->worker_pid; + + + tstatus = close_bpipe(bpipe); berrno be; - DMSG(ctx, DERROR, "Error closing command. Err=%s\n", be.bstrerror(tstatus)); - JMSG(ctx, M_ERROR, "Error closing command. Err=%s\n", be.bstrerror(tstatus)); - } + pm_strcpy(m_errmsg, be.bstrerror(tstatus)); + if (tstatus) + { + /* error during close */ + DMSG(ctx, DERROR, "Error closing command. Err=%s (%d)\n", m_errmsg.c_str()); + if (raise_error) + { + // raise it on request + JMSG(ctx, M_ERROR, "Error closing command. Err=%s (%d)\n", m_errmsg.c_str()); + } + } + + if (wpid) + { + /* terminate the process command */ + kill(wpid, SIGTERM); + } - // TODO: is it required to terminate the backend process? - // if (bpipe->worker_pid){ - // /* terminate the process command */ - // kill(bpipe->worker_pid, SIGTERM); - // } + bpipe = NULL; + } - bpipe = NULL; -}; + return tstatus; +} /* * Run command and prepared parameters. diff --git a/bacula/src/plugins/fd/pluginlib/execprog.h b/bacula/src/plugins/fd/pluginlib/execprog.h index e7700bb3c..225efe8e3 100644 --- a/bacula/src/plugins/fd/pluginlib/execprog.h +++ b/bacula/src/plugins/fd/pluginlib/execprog.h @@ -40,7 +40,7 @@ private: int wfd; // backend `stdin` to plugin file descriptor int efd; // backend `stderr` to plugin file descriptor int maxfd; // max file descriptors from bpipe channels - POOL_MEM errmsg; // message buffer for error string + POOL_MEM m_errmsg; /// message buffer for error string int extpipe; // set when data blast is performed using external pipe/file POOL_MEM extpipename; // name of the external pipe/file for restore bool f_eod; // the backend signaled EOD @@ -59,7 +59,7 @@ public: wfd(0), efd(0), maxfd(0), - errmsg(PM_MESSAGE), + m_errmsg(PM_MESSAGE), extpipe(-1), extpipename(PM_FNAME), f_eod(false), @@ -92,7 +92,7 @@ public: * @return true if connection is closed and we can't use bpipe object * @return false if connection is available */ - inline bool is_open() { return bpipe != NULL; }; + inline bool is_open() { return bpipe != NULL; } /** * @brief Checks if connection is closed and we can't use a bpipe object for communication. @@ -100,7 +100,7 @@ public: * @return true if connection is closed and we can't use bpipe object * @return false if connection is available */ - inline bool is_closed() { return bpipe == NULL; }; + inline bool is_closed() { return bpipe == NULL; } /** * @brief Checks if backend sent us some error, backend error message is flagged on f_error. @@ -108,7 +108,7 @@ public: * @return true * @return false */ - inline bool is_error() { return f_error || f_fatal; }; + inline bool is_error() { return f_error || f_fatal; } /** * @brief Checks if backend sent us fatal error, backend error message is flagged on f_fatal. @@ -116,19 +116,19 @@ public: * @return true * @return false */ - inline bool is_fatal() { return f_fatal || (f_error && abort_on_error); }; + inline bool is_fatal() { return f_fatal || (f_error && abort_on_error); } /** * @brief Set the abort on error object * */ - inline void set_abort_on_error() { abort_on_error = true; }; + inline void set_abort_on_error() { abort_on_error = true; } /** * @brief Clear abort_on_error flag. * */ - inline void clear_abort_on_error() { abort_on_error = false; }; + inline void clear_abort_on_error() { abort_on_error = false; } /** * @brief Return abort_on_error flag. @@ -136,7 +136,7 @@ public: * @return true * @return false */ - inline bool is_abort_on_error() { return abort_on_error; }; + inline bool is_abort_on_error() { return abort_on_error; } /** * @brief Checks if backend signaled EOD, eod from backend is flagged on f_eod. @@ -144,14 +144,14 @@ public: * @return true when backend signaled EOD on last packet * @return false when backend did not signal EOD */ - inline bool is_eod() { return f_eod; }; + inline bool is_eod() { return f_eod; } /** * @brief Clears the EOD from backend flag, f_eod. * The eod flag is set when EOD message received from backend and not cleared * until next recvbackend() call. */ - inline void clear_eod() { f_eod = false; }; + inline void clear_eod() { f_eod = false; } /** * @brief Get the cmd pid. @@ -167,7 +167,7 @@ public: return -1; }; - inline int get_terminate_status() { return tstatus; }; + inline int get_terminate_status() { return tstatus; } /* all you need is to simply execute the command first */ bool execute_command(bpContext *ctx, const char *cmd, const char *args = ""); @@ -185,9 +185,10 @@ public: int32_t write_data(bpContext *ctx, POOLMEM *buf, int32_t len); /* and finally terminate execution when finish */ - void terminate(bpContext *ctx, bool raise_error = true); + int terminate(bpContext *ctx, bool raise_error = true); - POOLMEM *get_error(bpContext *ctx); + inline POOL_MEM &get_error() noexcept { return m_errmsg; } + inline char *get_error_str() noexcept { return m_errmsg.c_str(); } /* direct pipe management */ inline int close_wpipe() { return ::close_wpipe(bpipe); }