Blob Blame History Raw
From f217d9e96dc8de88916e8ca0b93dd9a7500bbbc3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dan=20Vr=C3=A1til?= <dvratil@redhat.com>
Date: Tue, 6 May 2014 16:38:17 +0200
Subject: [PATCH 5/7] Fix PostgreSQL start when postmaster.pid is not removed
 after non-clean shutdown

When PostgreSQL is not terminated nicely, a pidfile is left behind in db_data,
which will prevent pg_ctl from starting a new PostgreSQL server.

We check for postmaster.pid file and verify that postgres server with PID
specified in the pidfile is not running anymore, then delete the pidfile to
allow pg_ctl to start a new server. If the postgres server is still running
(possibly after Akonadi server crash), we try to connect to it right away.

BUG: 286826
FIXED-IN: 1.12.2
---
 server/src/storage/dbconfigpostgresql.cpp | 37 +++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/server/src/storage/dbconfigpostgresql.cpp b/server/src/storage/dbconfigpostgresql.cpp
index 66e4605..7b61819 100644
--- a/server/src/storage/dbconfigpostgresql.cpp
+++ b/server/src/storage/dbconfigpostgresql.cpp
@@ -166,6 +166,43 @@ void DbConfigPostgresql::startInternalServer()
     QDir().mkpath( socketDir );
   }
 
+// TODO Windows support
+#ifndef Q_WS_WIN
+  // If postmaster.pid exists, check whether the postgres process still exists too,
+  // because normally we shouldn't be able to get this far if Akonadi is already
+  // running. If postgres is not running, then the pidfile was left after a system
+  // crash or something similar and we can remove it (otherwise pg_ctl won't start)
+  QFile postmaster( QString::fromLatin1( "%1/postmaster.pid" ).arg( mPgData ) );
+  if ( postmaster.exists() && postmaster.open( QIODevice::ReadOnly ) ) {
+    qDebug() << "Found a postmaster.pid pidfile, checking whether the server is still running...";
+    QByteArray pid = postmaster.readLine();
+    // Remvoe newline character
+    pid.truncate(pid.size() - 1);
+    QFile proc( QString::fromLatin1( "/proc/" + pid + "/stat" ) );
+    // Check whether the process with the PID from pidfile still exists and whether
+    // it's actually still postgres or, whether the PID has been recycled in the
+    // meanwhile.
+    if ( proc.open( QIODevice::ReadOnly ) ) {
+      const QByteArray stat = proc.readAll();
+      const QList<QByteArray> stats = stat.split( ' ' );
+      if ( stats.count() > 1 ) {
+        // Make sure the PID actually belongs to postgres process
+        if ( stats[1] == "(postgres)" ) {
+          // Yup, our PostgreSQL is actually running, so pretend we started the server
+          // and try to connect to it
+          qWarning() << "PostgreSQL for Akonadi is already running, trying to connect to it.";
+          return;
+        }
+      }
+      proc.close();
+    }
+
+    qDebug() << "No postgres process with specified PID is running. Removing the pidfile and starting a new Postgres instance...";
+    postmaster.close();
+    postmaster.remove();
+  }
+#endif
+
   if ( !QFile::exists( QString::fromLatin1( "%1/PG_VERSION" ).arg( mPgData ) ) ) {
     // postgres data directory not initialized yet, so call initdb on it
 
-- 
1.9.3