From f217d9e96dc8de88916e8ca0b93dd9a7500bbbc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dan=20Vr=C3=A1til?= 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 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