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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user