]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Fix #8159 About a deadlock when starting the Director with a missconfigured catalog
authorEric Bollengier <eric@baculasystems.com>
Thu, 16 Sep 2021 11:39:49 +0000 (13:39 +0200)
committerEric Bollengier <eric@baculasystems.com>
Thu, 24 Mar 2022 08:03:03 +0000 (09:03 +0100)
bacula/src/cats/postgresql.c
bacula/src/cats/sql.c

index cf6e254c8d334ed52074de181e5bc8598662d429..b1a378ee38a80f32fe27d0d89541156486022468 100644 (file)
@@ -65,6 +65,7 @@
 /* List of open databases */
 static dlist *db_list = NULL; 
 
+/* Do not issue a Jmsg() call inside the P/V for this mutex */
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
 
 BDB_POSTGRESQL::BDB_POSTGRESQL(): BDB()
@@ -203,20 +204,22 @@ get_out:
 } 
   
  
-/* Check that the database corresponds to the encoding we want  */
-static bool pgsql_check_database_encoding(JCR *jcr, BDB_POSTGRESQL *mdb)
+/* Check that the database corresponds to the encoding we want
+ * return: 0 OK, M_ERROR, M_FATAL, M_WARNING to print errmsg
+ */
+static int pgsql_check_database_encoding(JCR *jcr, BDB_POSTGRESQL *mdb)
 {
    SQL_ROW row;
    int ret = false; 
 
    if (!mdb->sql_query("SELECT getdatabaseencoding()", QF_STORE_RESULT)) { 
-      Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
-      return false; 
+      return M_ERROR;
    }
 
    if ((row = mdb->sql_fetch_row()) == NULL) { 
-      Mmsg1(mdb->errmsg, _("error fetching row: %s\n"), mdb->sql_strerror()); 
-      Jmsg(jcr, M_ERROR, 0, "Can't check database encoding %s", mdb->errmsg);
+      Mmsg1(mdb->errmsg, _("Can't check database encoding. Error fetching row: %s\n"), mdb->sql_strerror());
+      return M_ERROR;
+
    } else { 
       ret = bstrcmp(row[0], "SQL_ASCII");
 
@@ -229,11 +232,10 @@ static bool pgsql_check_database_encoding(JCR *jcr, BDB_POSTGRESQL *mdb)
          Mmsg(mdb->errmsg,
               _("Encoding error for database \"%s\". Wanted SQL_ASCII, got %s\n"),
               mdb->get_db_name(), row[0]); 
-         Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
-         Dmsg1(dbglvl_err, "%s", mdb->errmsg);
+         return M_WARNING;
       }
    }
-   return ret;
+   return 0;
 }
 
 /*
@@ -248,6 +250,7 @@ bool BDB_POSTGRESQL::bdb_open_database(JCR *jcr)
    int errstat;
    char buf[10], *port;
    BDB_POSTGRESQL *mdb = this;
+   int print_msg=0;             /* 1: warning, 2: error, 3 fatal */
 
    P(mutex);
    if (mdb->m_connected) {
@@ -338,10 +341,11 @@ bool BDB_POSTGRESQL::bdb_open_database(JCR *jcr)
 
    mdb->m_connected = true;
    if (!bdb_check_version(jcr)) {
+      print_msg = M_FATAL;
       goto get_out;
    }
 
-   sql_query("SET datestyle TO 'ISO, YMD'"); 
+   sql_query("SET datestyle TO 'ISO, YMD'");
    sql_query("SET cursor_tuple_fraction=1");
    sql_query("SET client_min_messages TO WARNING");
 
@@ -352,12 +356,17 @@ bool BDB_POSTGRESQL::bdb_open_database(JCR *jcr)
    sql_query("SET standard_conforming_strings=on"); 
  
    /* Check that encoding is SQL_ASCII */
-   pgsql_check_database_encoding(jcr, mdb);
+   print_msg = pgsql_check_database_encoding(jcr, mdb);
    retval = true; 
 
 get_out:
    V(mutex);
+   /* We can use Jmsg() only outside of the P/V because it can try to write to
+    * the DB, we should even not issue a Jmsg here
+    */
+   if (print_msg) {
+      Jmsg(jcr, print_msg, 0, "%s", errmsg);
+   }
    return retval; 
 } 
 
@@ -447,11 +456,11 @@ void BDB_POSTGRESQL::bdb_escape_string(JCR *jcr, char *snew, char *old, int len)
 
    PQescapeStringConn(mdb->m_db_handle, snew, old, len, &failed);
    if (failed) {
-      Jmsg(jcr, M_FATAL, 0, _("PQescapeStringConn returned non-zero.\n")); 
+      Jmsg(jcr, M_FATAL, 0, _("PQescapeStringConn returned non-zero.\n"));
       /* failed on encoding, probably invalid multibyte encoding in the source string
          see PQescapeStringConn documentation for details. */
       Dmsg0(dbglvl_err, "PQescapeStringConn failed\n");
-   } 
+   }
 }
 
 /*
@@ -461,12 +470,12 @@ void BDB_POSTGRESQL::bdb_escape_string(JCR *jcr, char *snew, char *old, int len)
 char *BDB_POSTGRESQL::bdb_escape_object(JCR *jcr, char *old, int len)
 {
    size_t new_len;
-   unsigned char *obj; 
+   unsigned char *obj;
    BDB_POSTGRESQL *mdb = this;
 
    mdb->esc_obj[0] = 0;
    obj = PQescapeByteaConn(mdb->m_db_handle, (unsigned const char *)old, len, &new_len);
-   if (!obj) { 
+   if (!obj) {
       Jmsg(jcr, M_FATAL, 0, _("PQescapeByteaConn returned NULL.\n"));
    } else {
       mdb->esc_obj = check_pool_memory_size(mdb->esc_obj, new_len+1);
index e07985a25eb0996c160e6da380a163cafea1e061..85434d7b526c9e17a15cd9df0565be09265351bb 100644 (file)
@@ -494,13 +494,11 @@ bool BDB::bdb_check_version(JCR *jcr)
  
    bacula_db_version = 0; 
    if (!bdb_sql_query(query, db_int_handler, (void *)&bacula_db_version)) { 
-      Jmsg(jcr, M_FATAL, 0, "%s", errmsg); 
       return false; 
    } 
    if (bacula_db_version != BDB_VERSION) { 
       Mmsg(errmsg, "Version error for database \"%s\". Wanted %d, got %d\n", 
           get_db_name(), BDB_VERSION, bacula_db_version); 
-      Jmsg(jcr, M_FATAL, 0, "%s", errmsg); 
       return false; 
    } 
    return true;