]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
metaplugin: Improve stderr handling from backend.
authorRadosław Korzeniewski <radoslaw@korzeniewski.net>
Tue, 28 Sep 2021 13:31:17 +0000 (15:31 +0200)
committerEric Bollengier <eric@baculasystems.com>
Wed, 6 Sep 2023 07:49:00 +0000 (09:49 +0200)
bacula/src/plugins/fd/pluginlib/ptcomm.cpp
bacula/src/plugins/fd/pluginlib/test_metaplugin_backend.c
regress/scripts/metaplugin-protocol-tests.sh

index 04881cee9327bee4da023b19a3f64d4caf70a803..b5246c4797d5eeefa0727ed66c37b36ee725fa7e 100644 (file)
@@ -79,8 +79,39 @@ void PTCOMM::terminate(bpContext *ctx)
       return;
    }
 
+   _timeout.tv_sec = 0;
+   _timeout.tv_usec = 1000;
+
+   fd_set rfds;
+   FD_ZERO(&rfds);
+   FD_SET(efd, &rfds);
+
+   int status = select(maxfd, &rfds, NULL, NULL, &_timeout);
+   if (status != 0)
+   {
+      // no timeout waiting for data, so its plausible that some data are available
+      if (FD_ISSET(efd, &rfds))
+      {
+         // do read of error channel
+         status = read(efd, errmsg.c_str(), errmsg.size() - 1);
+         errmsg.c_str()[status] = '\0'; // terminate string
+         strip_trailing_junk(errmsg.c_str());
+         if (status < 0)
+         {
+            /* show any error during message read */
+            berrno be;
+            DMSG(ctx, DERROR, "BPIPE read error on error channel: ERR=%s\n", be.bstrerror());
+            JMSG(ctx, M_ERROR, "BPIPE read error on error channel: ERR=%s\n", be.bstrerror());
+         } else {
+            // got data on error channel, report it
+            DMSG1(ctx, DERROR, "Backend reported error: %s\n", errmsg.c_str());
+            JMSG1(ctx, M_ERROR, "Backend reported error: %s\n", errmsg.c_str());
+         }
+      }
+   }
+
    pid_t worker_pid = bpipe->worker_pid;
-   int status = close_bpipe(bpipe);
+   status = close_bpipe(bpipe);
 
    bpipe = NULL;     // indicate closed bpipe
 
@@ -124,7 +155,7 @@ bool PTCOMM::recvbackend_data(bpContext *ctx, char *buf, int32_t nbytes)
    _timeout.tv_sec = PTCOMM_DEFAULT_TIMEOUT;
    _timeout.tv_usec = 0;
 
-   while (nbytes)
+   while (nbytes > 0)
    {
       fd_set rfds;
 
@@ -142,8 +173,11 @@ bool PTCOMM::recvbackend_data(bpContext *ctx, char *buf, int32_t nbytes)
          return false;
       }
 
-      // check if any data on error channel
-      if (FD_ISSET(efd, &rfds))
+      // check if data descriptor is ready
+      bool rfd_isset = FD_ISSET(rfd, &rfds);
+
+      // check if any messages on error channel when data channel is empty
+      if (FD_ISSET(efd, &rfds) && !rfd_isset)
       {
          // do read of error channel
          f_error = true;
@@ -163,8 +197,8 @@ bool PTCOMM::recvbackend_data(bpContext *ctx, char *buf, int32_t nbytes)
          }
       }
 
-      // check if data descriptor is ready
-      if (FD_ISSET(rfd, &rfds))
+      // handle data read
+      if (rfd_isset)
       {
          // do read of data
          status = read(rfd, buf + rbytes, nbytes);
@@ -193,13 +227,18 @@ bool PTCOMM::recvbackend_data(bpContext *ctx, char *buf, int32_t nbytes)
 }
 
 /**
- * @brief
+ * @brief Sends `nbytes` of data to backend from the buffer `buf`.
+ *
+ * This is a dedicated method for sending raw data to backend.
+ * It writes exact `nbytes` number of bytes from `buf`.
+ * It will not return until all requested data is sent or got error.
+ * The method handles errors and timeout writing data.
  *
- * @param ctx
- * @param buf
- * @param nbytes
- * @return true
- * @return false
+ * @param ctx - for Bacula debug jobinfo messages
+ * @param buf - the memory buffer from we will read data
+ * @param nbytes - the exact number of bytes to send to backend
+ * @return true - when send was successful
+ * @return false - on any error
  */
 bool PTCOMM::sendbackend_data(bpContext *ctx, const char *buf, int32_t nbytes)
 {
@@ -437,9 +476,10 @@ int32_t PTCOMM::recvbackend_header(bpContext *ctx, char *cmd, bool any)
 /**
  * @brief Handles a receive (read) packet header.
  *
- * @param ctx bpContext - for Bacula debug jobinfo messages
- * @param cmd
- * @return int32_t
+ * @param ctx for Bacula debug jobinfo messages
+ * @param cmd the expected command to receive or received
+ * @param any when true then it accepts any command received and saves it in `cmd`
+ * @return int32_t the packet length encoded in header
  */
 int32_t PTCOMM::handle_read_header(bpContext *ctx, char *cmd, bool any)
 {
index 1ecbc387eb7044e061ae771e5c3288f468a09827..dd53f6501282e8f0b80f93cc1220d87eaf4a8280 100644 (file)
@@ -191,6 +191,8 @@ void read_plugin_data_stream()
    }
 }
 
+// #define USE_PRINTF
+
 /**
  * @brief Sends/writes the data to plugin with assembling the raw packet.
  *
@@ -201,6 +203,7 @@ void write_plugin(const char cmd, const char *str)
 {
    int len;
    const char * out;
+   char header[9];
 
    if (str){
       len = strlen(str);
@@ -209,9 +212,15 @@ void write_plugin(const char cmd, const char *str)
       len = 0;
       out = "";
    }
+#ifdef USE_PRINTF
    printf("%c%06d\n", cmd, len);
    printf("%s", out);
    fflush(stdout);
+#else
+   snprintf(header, 9, "%c%06d\n", cmd, len);
+   write(STDOUT_FILENO, header, 8);
+   write(STDOUT_FILENO, out, len);
+#endif
    snprintf(buflog, BUFLEN, "<< %c%06d:%s", cmd, len, out);
    LOG(buflog);
 }
index 45687e8f07b20675de3ee2cb4c4839ebb0b6d5b0..fa1520b47253c26fa64082af757543e3ba9f6f63 100755 (executable)
@@ -470,10 +470,10 @@ fi
 
 RET=$(grep "jobstatus:" ${cwd}/tmp/log6.out | awk '{print $2}')
 COMME=$(grep -c COMM_STDERR ${cwd}/tmp/log6.out)
-BEND=$(grep -w -c "TESTEND" ${cwd}/tmp/log6.out)
-if [ "x$RET" != "xT" ] || [ "$COMME" -ne 1 ] || [ "$BEND" -ne 1 ]
+#BEND=$(grep -w -c "TESTEND" ${cwd}/tmp/log6.out)
+if [ "x$RET" != "xT" ] || [ "$COMME" -ne 1 ]
 then
-   echo "log6" "$RET" "$COMME" "$BEND"
+   echo "log6" "$RET" "$COMME"
    bstat=$((bstat+16))
 fi