Rex Dieter 78fb1bf
From f217d9e96dc8de88916e8ca0b93dd9a7500bbbc3 Mon Sep 17 00:00:00 2001
Rex Dieter 78fb1bf
From: =?UTF-8?q?Dan=20Vr=C3=A1til?= <dvratil@redhat.com>
Rex Dieter 78fb1bf
Date: Tue, 6 May 2014 16:38:17 +0200
Rex Dieter 78fb1bf
Subject: [PATCH 5/7] Fix PostgreSQL start when postmaster.pid is not removed
Rex Dieter 78fb1bf
 after non-clean shutdown
Rex Dieter 78fb1bf
Rex Dieter 78fb1bf
When PostgreSQL is not terminated nicely, a pidfile is left behind in db_data,
Rex Dieter 78fb1bf
which will prevent pg_ctl from starting a new PostgreSQL server.
Rex Dieter 78fb1bf
Rex Dieter 78fb1bf
We check for postmaster.pid file and verify that postgres server with PID
Rex Dieter 78fb1bf
specified in the pidfile is not running anymore, then delete the pidfile to
Rex Dieter 78fb1bf
allow pg_ctl to start a new server. If the postgres server is still running
Rex Dieter 78fb1bf
(possibly after Akonadi server crash), we try to connect to it right away.
Rex Dieter 78fb1bf
Rex Dieter 78fb1bf
BUG: 286826
Rex Dieter 78fb1bf
FIXED-IN: 1.12.2
Rex Dieter 78fb1bf
---
Rex Dieter 78fb1bf
 server/src/storage/dbconfigpostgresql.cpp | 37 +++++++++++++++++++++++++++++++
Rex Dieter 78fb1bf
 1 file changed, 37 insertions(+)
Rex Dieter 78fb1bf
Rex Dieter 78fb1bf
diff --git a/server/src/storage/dbconfigpostgresql.cpp b/server/src/storage/dbconfigpostgresql.cpp
Rex Dieter 78fb1bf
index 66e4605..7b61819 100644
Rex Dieter 78fb1bf
--- a/server/src/storage/dbconfigpostgresql.cpp
Rex Dieter 78fb1bf
+++ b/server/src/storage/dbconfigpostgresql.cpp
Rex Dieter 78fb1bf
@@ -166,6 +166,43 @@ void DbConfigPostgresql::startInternalServer()
Rex Dieter 78fb1bf
     QDir().mkpath( socketDir );
Rex Dieter 78fb1bf
   }
Rex Dieter 78fb1bf
 
Rex Dieter 78fb1bf
+// TODO Windows support
Rex Dieter 78fb1bf
+#ifndef Q_WS_WIN
Rex Dieter 78fb1bf
+  // If postmaster.pid exists, check whether the postgres process still exists too,
Rex Dieter 78fb1bf
+  // because normally we shouldn't be able to get this far if Akonadi is already
Rex Dieter 78fb1bf
+  // running. If postgres is not running, then the pidfile was left after a system
Rex Dieter 78fb1bf
+  // crash or something similar and we can remove it (otherwise pg_ctl won't start)
Rex Dieter 78fb1bf
+  QFile postmaster( QString::fromLatin1( "%1/postmaster.pid" ).arg( mPgData ) );
Rex Dieter 78fb1bf
+  if ( postmaster.exists() && postmaster.open( QIODevice::ReadOnly ) ) {
Rex Dieter 78fb1bf
+    qDebug() << "Found a postmaster.pid pidfile, checking whether the server is still running...";
Rex Dieter 78fb1bf
+    QByteArray pid = postmaster.readLine();
Rex Dieter 78fb1bf
+    // Remvoe newline character
Rex Dieter 78fb1bf
+    pid.truncate(pid.size() - 1);
Rex Dieter 78fb1bf
+    QFile proc( QString::fromLatin1( "/proc/" + pid + "/stat" ) );
Rex Dieter 78fb1bf
+    // Check whether the process with the PID from pidfile still exists and whether
Rex Dieter 78fb1bf
+    // it's actually still postgres or, whether the PID has been recycled in the
Rex Dieter 78fb1bf
+    // meanwhile.
Rex Dieter 78fb1bf
+    if ( proc.open( QIODevice::ReadOnly ) ) {
Rex Dieter 78fb1bf
+      const QByteArray stat = proc.readAll();
Rex Dieter 78fb1bf
+      const QList<QByteArray> stats = stat.split( ' ' );
Rex Dieter 78fb1bf
+      if ( stats.count() > 1 ) {
Rex Dieter 78fb1bf
+        // Make sure the PID actually belongs to postgres process
Rex Dieter 78fb1bf
+        if ( stats[1] == "(postgres)" ) {
Rex Dieter 78fb1bf
+          // Yup, our PostgreSQL is actually running, so pretend we started the server
Rex Dieter 78fb1bf
+          // and try to connect to it
Rex Dieter 78fb1bf
+          qWarning() << "PostgreSQL for Akonadi is already running, trying to connect to it.";
Rex Dieter 78fb1bf
+          return;
Rex Dieter 78fb1bf
+        }
Rex Dieter 78fb1bf
+      }
Rex Dieter 78fb1bf
+      proc.close();
Rex Dieter 78fb1bf
+    }
Rex Dieter 78fb1bf
+
Rex Dieter 78fb1bf
+    qDebug() << "No postgres process with specified PID is running. Removing the pidfile and starting a new Postgres instance...";
Rex Dieter 78fb1bf
+    postmaster.close();
Rex Dieter 78fb1bf
+    postmaster.remove();
Rex Dieter 78fb1bf
+  }
Rex Dieter 78fb1bf
+#endif
Rex Dieter 78fb1bf
+
Rex Dieter 78fb1bf
   if ( !QFile::exists( QString::fromLatin1( "%1/PG_VERSION" ).arg( mPgData ) ) ) {
Rex Dieter 78fb1bf
     // postgres data directory not initialized yet, so call initdb on it
Rex Dieter 78fb1bf
 
Rex Dieter 78fb1bf
-- 
Rex Dieter 78fb1bf
1.9.3
Rex Dieter 78fb1bf