do not use exit()

We avoid using exit() to be able to clean up when we have to
terminate. This includes removal of the PID file as well as closing
database connections.
This commit is contained in:
Christian Kruse
2014-01-17 11:28:55 +01:00
parent 94cb5b94e7
commit ee9dc9e247

View File

@@ -138,6 +138,8 @@ static volatile sig_atomic_t got_SIGHUP = false;
static void handle_sighup(SIGNAL_ARGS); static void handle_sighup(SIGNAL_ARGS);
static void handle_sigint(SIGNAL_ARGS); static void handle_sigint(SIGNAL_ARGS);
static void terminate(int retval);
#ifndef WIN32 #ifndef WIN32
static void setup_event_handlers(void); static void setup_event_handlers(void);
#endif #endif
@@ -269,7 +271,7 @@ main(int argc, char **argv)
{ {
log_err(_("Node information is missing. " log_err(_("Node information is missing. "
"Check the configuration file, or provide one if you have not done so.\n")); "Check the configuration file, or provide one if you have not done so.\n"));
exit(ERR_BAD_CONFIG); terminate(ERR_BAD_CONFIG);
} }
fclose(stdin); fclose(stdin);
@@ -291,8 +293,7 @@ main(int argc, char **argv)
{ {
if(ret_ver != NULL) if(ret_ver != NULL)
log_err(_("%s needs standby to be PostgreSQL 9.0 or better\n"), progname); log_err(_("%s needs standby to be PostgreSQL 9.0 or better\n"), progname);
PQfinish(myLocalConn); terminate(ERR_BAD_CONFIG);
exit(ERR_BAD_CONFIG);
} }
@@ -327,7 +328,7 @@ main(int argc, char **argv)
* should not exit at this point, but for now we do until we have a * should not exit at this point, but for now we do until we have a
* better strategy */ * better strategy */
if (ret == -1) if (ret == -1)
exit(1); terminate(1);
switch (myLocalMode) switch (myLocalMode)
{ {
@@ -371,7 +372,7 @@ main(int argc, char **argv)
/* XXX /* XXX
* May we do something more verbose ? * May we do something more verbose ?
*/ */
exit(1); terminate(1);
} }
if (got_SIGHUP) if (got_SIGHUP)
@@ -404,8 +405,7 @@ main(int argc, char **argv)
&primary_options.node, NULL); &primary_options.node, NULL);
if (primaryConn == NULL) if (primaryConn == NULL)
{ {
CloseConnections(); terminate(ERR_BAD_CONFIG);
exit(ERR_BAD_CONFIG);
} }
checkClusterConfiguration(myLocalConn, primaryConn); checkClusterConfiguration(myLocalConn, primaryConn);
@@ -493,8 +493,7 @@ WitnessMonitor(void)
* If we can't reconnect, just exit... * If we can't reconnect, just exit...
* XXX we need to make witness connect to the new master * XXX we need to make witness connect to the new master
*/ */
PQfinish(myLocalConn); terminate(0);
exit(0);
} }
/* Fast path for the case where no history is requested */ /* Fast path for the case where no history is requested */
@@ -575,7 +574,7 @@ StandbyMonitor(void)
if (!CheckConnection(myLocalConn, "standby")) if (!CheckConnection(myLocalConn, "standby"))
{ {
handle_sigint(0); terminate(1);
} }
if (PQstatus(primaryConn) != CONNECTION_OK) if (PQstatus(primaryConn) != CONNECTION_OK)
@@ -604,7 +603,7 @@ StandbyMonitor(void)
if (PQstatus(primaryConn) != CONNECTION_OK) if (PQstatus(primaryConn) != CONNECTION_OK)
{ {
log_err(_("We couldn't reconnect for long enough, exiting...\n")); log_err(_("We couldn't reconnect for long enough, exiting...\n"));
exit(ERR_DB_CON); terminate(ERR_DB_CON);
} }
} }
else if (local_options.failover == AUTOMATIC_FAILOVER) else if (local_options.failover == AUTOMATIC_FAILOVER)
@@ -626,8 +625,7 @@ StandbyMonitor(void)
{ {
case 0: case 0:
log_err(_("It seems like we have been promoted, so exit from monitoring...\n")); log_err(_("It seems like we have been promoted, so exit from monitoring...\n"));
CloseConnections(); terminate(1);
handle_sigint(0);
break; break;
case -1: case -1:
@@ -636,7 +634,7 @@ StandbyMonitor(void)
if (!CheckConnection(myLocalConn, "standby")) if (!CheckConnection(myLocalConn, "standby"))
{ {
handle_sigint(0); terminate(0);
} }
break; break;
@@ -770,8 +768,7 @@ do_failover(void)
{ {
log_err(_("Can't get nodes' info: %s\n"), PQerrorMessage(myLocalConn)); log_err(_("Can't get nodes' info: %s\n"), PQerrorMessage(myLocalConn));
PQclear(res); PQclear(res);
PQfinish(myLocalConn); terminate(ERR_DB_QUERY);
exit(ERR_DB_QUERY);
} }
/* /*
@@ -820,7 +817,7 @@ do_failover(void)
log_err(_("Can't reach most of the nodes.\n" log_err(_("Can't reach most of the nodes.\n"
"Let the other standby servers decide which one will be the primary.\n" "Let the other standby servers decide which one will be the primary.\n"
"Manual action will be needed to readd this node to the cluster.\n")); "Manual action will be needed to readd this node to the cluster.\n"));
exit(ERR_FAILOVER_FAIL); terminate(ERR_FAILOVER_FAIL);
} }
/* Query all the nodes to determine which ones are ready */ /* Query all the nodes to determine which ones are ready */
@@ -841,7 +838,7 @@ do_failover(void)
if (PQstatus(nodeConn) != CONNECTION_OK) if (PQstatus(nodeConn) != CONNECTION_OK)
{ {
log_err(_("It seems new problems are arising, manual intervention is needed\n")); log_err(_("It seems new problems are arising, manual intervention is needed\n"));
exit(ERR_FAILOVER_FAIL); terminate(ERR_FAILOVER_FAIL);
} }
sqlquery_snprintf(sqlquery, "SELECT pg_last_xlog_receive_location()"); sqlquery_snprintf(sqlquery, "SELECT pg_last_xlog_receive_location()");
@@ -852,7 +849,7 @@ do_failover(void)
log_info(_("Connection details: %s\n"), nodes[i].conninfostr); log_info(_("Connection details: %s\n"), nodes[i].conninfostr);
PQclear(res); PQclear(res);
PQfinish(nodeConn); PQfinish(nodeConn);
exit(ERR_FAILOVER_FAIL); terminate(ERR_FAILOVER_FAIL);
} }
if (sscanf(PQgetvalue(res, 0, 0), "%X/%X", &uxlogid, &uxrecoff) != 2) if (sscanf(PQgetvalue(res, 0, 0), "%X/%X", &uxlogid, &uxrecoff) != 2)
@@ -867,7 +864,7 @@ do_failover(void)
PQclear(res); PQclear(res);
PQfinish(nodeConn); PQfinish(nodeConn);
log_info(_("InvalidXLogRecPtr detected in a standby\n")); log_info(_("InvalidXLogRecPtr detected in a standby\n"));
exit(ERR_FAILOVER_FAIL); terminate(ERR_FAILOVER_FAIL);
} }
XLAssignValue(nodes[i].xlog_location, uxlogid, uxrecoff); XLAssignValue(nodes[i].xlog_location, uxlogid, uxrecoff);
@@ -882,11 +879,10 @@ do_failover(void)
if (PQresultStatus(res) != PGRES_TUPLES_OK) if (PQresultStatus(res) != PGRES_TUPLES_OK)
{ {
log_err(_("PQexec failed: %s.\nReport an invalid value to not be considered as new primary and exit.\n"), PQerrorMessage(myLocalConn)); log_err(_("PQexec failed: %s.\nReport an invalid value to not be considered as new primary and exit.\n"), PQerrorMessage(myLocalConn));
PQfinish(myLocalConn);
PQclear(res); PQclear(res);
sprintf(last_wal_standby_applied, "'%X/%X'", 0, 0); sprintf(last_wal_standby_applied, "'%X/%X'", 0, 0);
update_shared_memory(last_wal_standby_applied); update_shared_memory(last_wal_standby_applied);
exit(ERR_DB_QUERY); terminate(ERR_DB_QUERY);
} }
/* write last location in shared memory */ /* write last location in shared memory */
@@ -938,7 +934,7 @@ do_failover(void)
log_err(_("PQexec failed: %s.\nReport an invalid value to not be considered as new primary and exit.\n"), PQerrorMessage(nodeConn)); log_err(_("PQexec failed: %s.\nReport an invalid value to not be considered as new primary and exit.\n"), PQerrorMessage(nodeConn));
PQclear(res); PQclear(res);
PQfinish(nodeConn); PQfinish(nodeConn);
exit(ERR_DB_QUERY); terminate(ERR_DB_QUERY);
} }
if (sscanf(PQgetvalue(res, 0, 0), "%X/%X", &uxlogid, &uxrecoff) != 2) if (sscanf(PQgetvalue(res, 0, 0), "%X/%X", &uxlogid, &uxrecoff) != 2)
@@ -1012,7 +1008,7 @@ do_failover(void)
if (best_candidate.is_witness) if (best_candidate.is_witness)
{ {
log_err(_("%s: Node selected as new master is a witness. Can't be promoted.\n"), progname); log_err(_("%s: Node selected as new master is a witness. Can't be promoted.\n"), progname);
exit(ERR_FAILOVER_FAIL); terminate(ERR_FAILOVER_FAIL);
} }
/* wait */ /* wait */
@@ -1026,7 +1022,7 @@ do_failover(void)
if (r != 0) if (r != 0)
{ {
log_err(_("%s: promote command failed. You could check and try it manually.\n"), progname); log_err(_("%s: promote command failed. You could check and try it manually.\n"), progname);
exit(ERR_BAD_CONFIG); terminate(ERR_BAD_CONFIG);
} }
} }
else if (find_best) else if (find_best)
@@ -1046,13 +1042,13 @@ do_failover(void)
if (r != 0) if (r != 0)
{ {
log_err(_("%s: follow command failed. You could check and try it manually.\n"), progname); log_err(_("%s: follow command failed. You could check and try it manually.\n"), progname);
exit(ERR_BAD_CONFIG); terminate(ERR_BAD_CONFIG);
} }
} }
else else
{ {
log_err(_("%s: Did not find candidates. You should check and try manually.\n"), progname); log_err(_("%s: Did not find candidates. You should check and try manually.\n"), progname);
exit(ERR_FAILOVER_FAIL); terminate(ERR_FAILOVER_FAIL);
} }
/* to force it to re-calculate mode and master node */ /* to force it to re-calculate mode and master node */
@@ -1119,8 +1115,7 @@ checkClusterConfiguration(PGconn *conn, PGconn *primary)
{ {
log_err(_("PQexec failed: %s\n"), PQerrorMessage(conn)); log_err(_("PQexec failed: %s\n"), PQerrorMessage(conn));
PQclear(res); PQclear(res);
CloseConnections(); terminate(ERR_DB_QUERY);
exit(ERR_DB_QUERY);
} }
/* /*
@@ -1134,8 +1129,7 @@ checkClusterConfiguration(PGconn *conn, PGconn *primary)
{ {
log_err(_("The replication cluster is not configured\n")); log_err(_("The replication cluster is not configured\n"));
PQclear(res); PQclear(res);
CloseConnections(); terminate(ERR_BAD_CONFIG);
exit(ERR_BAD_CONFIG);
} }
PQclear(res); PQclear(res);
} }
@@ -1161,8 +1155,7 @@ checkNodeConfiguration(char *conninfo)
{ {
log_err(_("PQexec failed: %s\n"), PQerrorMessage(myLocalConn)); log_err(_("PQexec failed: %s\n"), PQerrorMessage(myLocalConn));
PQclear(res); PQclear(res);
CloseConnections(); terminate(ERR_BAD_CONFIG);
exit(ERR_BAD_CONFIG);
} }
/* /*
@@ -1177,8 +1170,7 @@ checkNodeConfiguration(char *conninfo)
if (myLocalMode == WITNESS_MODE) if (myLocalMode == WITNESS_MODE)
{ {
log_err(_("The witness is not configured\n")); log_err(_("The witness is not configured\n"));
CloseConnections(); terminate(ERR_BAD_CONFIG);
exit(ERR_BAD_CONFIG);
} }
/* Adding the node */ /* Adding the node */
@@ -1195,8 +1187,7 @@ checkNodeConfiguration(char *conninfo)
{ {
log_err(_("Cannot insert node details, %s\n"), log_err(_("Cannot insert node details, %s\n"),
PQerrorMessage(primaryConn)); PQerrorMessage(primaryConn));
CloseConnections(); terminate(ERR_BAD_CONFIG);
exit(ERR_BAD_CONFIG);
} }
} }
else else
@@ -1248,15 +1239,7 @@ void help(const char *progname)
static void static void
handle_sigint(SIGNAL_ARGS) handle_sigint(SIGNAL_ARGS)
{ {
CloseConnections(); terminate(0);
logger_shutdown();
if (pid_file)
{
remove(pid_file);
}
exit(1);
} }
/* SIGHUP: set flag to re-read config file at next convenient time */ /* SIGHUP: set flag to re-read config file at next convenient time */
@@ -1275,6 +1258,20 @@ setup_event_handlers(void)
} }
#endif #endif
static void
terminate(int retval)
{
CloseConnections();
logger_shutdown();
if (pid_file)
{
remove(pid_file);
}
exit(retval);
}
static void static void
update_shared_memory(char *last_wal_standby_applied) update_shared_memory(char *last_wal_standby_applied)
@@ -1309,8 +1306,7 @@ update_registration(void)
if (PQresultStatus(res) != PGRES_COMMAND_OK) if (PQresultStatus(res) != PGRES_COMMAND_OK)
{ {
log_err(_("Cannot update registration: %s\n"), PQerrorMessage(primaryConn)); log_err(_("Cannot update registration: %s\n"), PQerrorMessage(primaryConn));
CloseConnections(); terminate(ERR_DB_CON);
exit(ERR_DB_CON);
} }
PQclear(res); PQclear(res);
} }