]> git.sur5r.net Git - bacula/bacula/commitdiff
Fix for bug #1569 deadlock/crash in Dir
authorKern Sibbald <kern@sibbald.com>
Sun, 23 May 2010 16:37:10 +0000 (18:37 +0200)
committerKern Sibbald <kern@sibbald.com>
Sun, 23 May 2010 16:38:01 +0000 (18:38 +0200)
bacula/src/bacula.h
bacula/src/lib/message.c
bacula/src/lib/parse_conf.h

index ab0ba1abd02449e2f99935184ade6a348c0ed0a5..bab5f1f8bad20cfecfa7ccf3ae0b603a2afd67b8 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -28,7 +28,6 @@
 /*
  * bacula.h -- main header file to include in all Bacula source
  *
- *   Version $Id$
  */
 
 #ifndef _BACULA_H
index 6d951e2bbfd20fec13cf0bd1f40af084ddda94bc..e403ec9ea70c577e5a6784fd53eac834cb0de41c 100644 (file)
@@ -89,6 +89,30 @@ const char *host_os = HOST_OS;
 const char *distname = DISTNAME;
 const char *distver = DISTVER;
 
+/* Some message class methods */
+void MSGS::lock()
+{
+   P(fides_mutex);
+}
+
+void MSGS::unlock()
+{
+   V(fides_mutex);
+}
+
+/*
+ * Wait for not in use variable to be clear
+ */
+void MSGS::wait_not_in_use()     /* leaves fides_mutex set */
+{
+   lock();
+   while (m_in_use) {
+      unlock();
+      bmicrosleep(0, 200);         /* wait */
+      lock();
+   }
+}
+
 /*
  * Handle message delivery errors
  */
@@ -300,6 +324,7 @@ init_msg(JCR *jcr, MSGS *msg)
       daemon_msgs->dest_chain = temp_chain;
       memcpy(daemon_msgs->send_msg, msg->send_msg, sizeof(msg->send_msg));
    }
+
    Dmsg2(250, "Copy message resource %p to %p\n", msg, temp_chain);
 
 }
@@ -468,7 +493,15 @@ void close_msg(JCR *jcr)
    if (msgs == NULL) {
       return;
    }
-   P(fides_mutex);
+
+   /* Wait for item to be not in use, then mark closing */
+   if (msgs->is_closing()) {
+      return;
+   }
+   msgs->wait_not_in_use();          /* leaves fides_mutex set */
+   msgs->set_closing();
+   msgs->unlock();
+
    Dmsg1(850, "===Begin close msg resource at %p\n", msgs);
    cmd = get_pool_memory(PM_MESSAGE);
    for (d=msgs->dest_chain; d; ) {
@@ -552,12 +585,13 @@ rem_temp_file:
       }
       d = d->next;                    /* point to next buffer */
    }
-   V(fides_mutex);
    free_pool_memory(cmd);
    Dmsg0(850, "Done walking message chain.\n");
    if (jcr) {
       free_msgs_res(msgs);
       msgs = NULL;
+   } else {
+      msgs->clear_closing();
    }
    Dmsg0(850, "===End close msg resource\n");
 }
@@ -697,6 +731,18 @@ void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
     if (msgs == NULL) {
        msgs = daemon_msgs;
     }
+    /*
+     * If closing this message resource, print and send to syslog,
+     *   then get out.
+     */
+    if (msgs->is_closing()) {
+       fputs(dt, stdout);
+       fputs(msg, stdout);
+       fflush(stdout);
+       syslog(LOG_DAEMON|LOG_ERR, "%s", msg);
+       return;
+    }
+
     for (d=msgs->dest_chain; d; d=d->next) {
        if (bit_is_set(type, d->msg_types)) {
           switch (d->dest_code) {
@@ -778,7 +824,10 @@ void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
              case MD_MAIL_ON_ERROR:
              case MD_MAIL_ON_SUCCESS:
                 Dmsg1(850, "MAIL for following msg: %s", msg);
-                P(fides_mutex);
+                if (msgs->is_closing()) {
+                   break;
+                }
+                msgs->set_in_use();
                 if (!d->fd) {
                    POOLMEM *name = get_pool_memory(PM_MESSAGE);
                    make_unique_mail_filename(jcr, name, d);
@@ -799,7 +848,7 @@ void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
                    d->max_len = len;      /* keep max line length */
                 }
                 fputs(msg, d->fd);
-                V(fides_mutex);
+                msgs->clear_in_use();
                 break;
              case MD_APPEND:
                 Dmsg1(850, "APPEND for following msg: %s", msg);
@@ -809,9 +858,12 @@ void dispatch_message(JCR *jcr, int type, utime_t mtime, char *msg)
                 Dmsg1(850, "FILE for following msg: %s", msg);
                 mode = "w+b";
 send_to_file:
-                P(fides_mutex);
+                if (msgs->is_closing()) {
+                   break;
+                }
+                msgs->set_in_use();
                 if (!d->fd && !open_dest_file(jcr, d, mode)) {
-                   V(fides_mutex);
+                   msgs->clear_in_use();
                    break;
                 }
                 fputs(dt, d->fd);
@@ -825,7 +877,7 @@ send_to_file:
                       fputs(msg, d->fd);
                    }
                 }
-                V(fides_mutex);
+                msgs->clear_in_use();
                 break;
              case MD_DIRECTOR:
                 Dmsg1(850, "DIRECTOR for following msg: %s", msg);
index c4711ed643ae036e2c7a5b940ed225da87c98d54..2d84752868bc193b31c266c436bfd6d7119493ac 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -29,8 +29,6 @@
  *
  *     Kern Sibbald, January MM
  *
- *   Version $Id$
- *
  */
 
 struct RES_ITEM;                    /* Declare forward referenced structure */
@@ -137,8 +135,22 @@ public:
    DEST *dest_chain;                  /* chain of destinations */
    char send_msg[nbytes_for_bits(M_MAX+1)];  /* bit array of types */
 
+private:
+   bool m_in_use;                     /* set when using to send a message */
+   bool m_closing;                    /* set when closing message resource */
+
+public:
    /* Methods */
    char *name() const;
+   void clear_in_use() { lock(); m_in_use=false; unlock(); }
+   void set_in_use() { wait_not_in_use(); m_in_use=true; unlock(); }
+   void set_closing() { m_closing=true; }
+   void clear_closing() { lock(); m_closing=false; unlock(); }
+   bool is_closing() { lock(); bool rtn=m_closing; unlock(); return rtn; }
+
+   void wait_not_in_use();            /* in message.c */
+   void lock();                       /* in message.c */
+   void unlock();                     /* in message.c */
 };
 
 inline char *MSGS::name() const { return hdr.name; }