ha: Recreate the control FIFO if the file exists but is not a FIFO

This may happen if something like `echo ... > /path/to/fifo` is used
before the plugin was able to create the FIFO. In that case we'd end
up in a loop always reading the same values from the static file.
This commit is contained in:
Tobias Brunner
2015-08-17 17:51:20 +02:00
parent 636b2e9b2a
commit fffee7c759
+68 -13
View File
@@ -1,4 +1,5 @@
/* /*
* Copyright (C) 2015 Tobias Brunner
* Copyright (C) 2008 Martin Willi * Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
@@ -50,6 +51,41 @@ struct private_ha_ctl_t {
ha_cache_t *cache; ha_cache_t *cache;
}; };
/**
* Change the permissions of the control FIFO, returns TRUE on success
*/
static bool change_fifo_permissions()
{
if (chown(HA_FIFO, lib->caps->get_uid(lib->caps),
lib->caps->get_gid(lib->caps)) != 0)
{
DBG1(DBG_CFG, "changing HA FIFO permissions failed: %s",
strerror(errno));
return FALSE;
}
return TRUE;
}
/**
* Deletes and creates the control FIFO, returns TRUE on success
*/
static bool recreate_fifo()
{
mode_t old;
bool success = TRUE;
unlink(HA_FIFO);
old = umask(S_IRWXO);
if (mkfifo(HA_FIFO, S_IRUSR | S_IWUSR) != 0)
{
DBG1(DBG_CFG, "creating HA FIFO %s failed: %s", HA_FIFO,
strerror(errno));
success = FALSE;
}
umask(old);
return success && change_fifo_permissions();
}
/** /**
* FIFO dispatching function * FIFO dispatching function
*/ */
@@ -59,13 +95,22 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
bool oldstate; bool oldstate;
char buf[8]; char buf[8];
u_int segment; u_int segment;
struct stat sb;
oldstate = thread_cancelability(TRUE); oldstate = thread_cancelability(TRUE);
fifo = open(HA_FIFO, O_RDONLY); fifo = open(HA_FIFO, O_RDONLY);
thread_cancelability(oldstate); thread_cancelability(oldstate);
if (fifo == -1) if (fifo == -1 || fstat(fifo, &sb) != 0 || !S_ISFIFO(sb.st_mode))
{ {
DBG1(DBG_CFG, "opening HA fifo failed: %s", strerror(errno)); if (fifo == -1 && errno != ENOENT)
{
DBG1(DBG_CFG, "opening HA FIFO failed: %s", strerror(errno));
}
else
{
DBG1(DBG_CFG, "%s is not a FIFO, recreate it", HA_FIFO);
recreate_fifo();
}
sleep(1); sleep(1);
return JOB_REQUEUE_FAIR; return JOB_REQUEUE_FAIR;
} }
@@ -100,6 +145,7 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
METHOD(ha_ctl_t, destroy, void, METHOD(ha_ctl_t, destroy, void,
private_ha_ctl_t *this) private_ha_ctl_t *this)
{ {
unlink(HA_FIFO);
free(this); free(this);
} }
@@ -109,7 +155,7 @@ METHOD(ha_ctl_t, destroy, void,
ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache) ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
{ {
private_ha_ctl_t *this; private_ha_ctl_t *this;
mode_t old; struct stat sb;
INIT(this, INIT(this,
.public = { .public = {
@@ -119,20 +165,30 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
.cache = cache, .cache = cache,
); );
if (access(HA_FIFO, R_OK|W_OK) != 0) if (stat(HA_FIFO, &sb) == 0)
{ {
old = umask(S_IRWXO); if (!S_ISFIFO(sb.st_mode))
if (mkfifo(HA_FIFO, S_IRUSR | S_IWUSR) != 0)
{ {
DBG1(DBG_CFG, "creating HA FIFO %s failed: %s", DBG1(DBG_CFG, "%s is not a FIFO, recreate it", HA_FIFO);
HA_FIFO, strerror(errno)); recreate_fifo();
}
else if (access(HA_FIFO, R_OK|W_OK) != 0)
{
DBG1(DBG_CFG, "accessing HA FIFO %s denied, recreate it", HA_FIFO);
recreate_fifo();
}
else
{
change_fifo_permissions();
} }
umask(old);
} }
if (chown(HA_FIFO, lib->caps->get_uid(lib->caps), else if (errno == ENOENT)
lib->caps->get_gid(lib->caps)) != 0)
{ {
DBG1(DBG_CFG, "changing HA FIFO permissions failed: %s", recreate_fifo();
}
else
{
DBG1(DBG_CFG, "accessing HA FIFO %s failed: %s", HA_FIFO,
strerror(errno)); strerror(errno));
} }
@@ -141,4 +197,3 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL)); this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public; return &this->public;
} }