shunt-manager: Add flush() method to properly uninstall shunts
This will allow us to uninstall shunts before unloading the kernel-interface plugins.
This commit is contained in:
@@ -19,8 +19,11 @@
|
|||||||
#include <hydra.h>
|
#include <hydra.h>
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
#include <threading/rwlock.h>
|
#include <threading/rwlock.h>
|
||||||
|
#include <threading/rwlock_condvar.h>
|
||||||
#include <collections/linked_list.h>
|
#include <collections/linked_list.h>
|
||||||
|
|
||||||
|
#define INSTALL_DISABLED ((u_int)~0)
|
||||||
|
|
||||||
typedef struct private_shunt_manager_t private_shunt_manager_t;
|
typedef struct private_shunt_manager_t private_shunt_manager_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +45,16 @@ struct private_shunt_manager_t {
|
|||||||
* Lock to safely access the list of shunts
|
* Lock to safely access the list of shunts
|
||||||
*/
|
*/
|
||||||
rwlock_t *lock;
|
rwlock_t *lock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of threads currently installing shunts, or INSTALL_DISABLED
|
||||||
|
*/
|
||||||
|
u_int installing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Condvar to signal shunt installation
|
||||||
|
*/
|
||||||
|
rwlock_condvar_t *condvar;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,6 +139,11 @@ METHOD(shunt_manager_t, install, bool,
|
|||||||
|
|
||||||
/* check if not already installed */
|
/* check if not already installed */
|
||||||
this->lock->write_lock(this->lock);
|
this->lock->write_lock(this->lock);
|
||||||
|
if (this->installing == INSTALL_DISABLED)
|
||||||
|
{ /* flush() has been called */
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
enumerator = this->shunts->create_enumerator(this->shunts);
|
enumerator = this->shunts->create_enumerator(this->shunts);
|
||||||
while (enumerator->enumerate(enumerator, &child_cfg))
|
while (enumerator->enumerate(enumerator, &child_cfg))
|
||||||
{
|
{
|
||||||
@@ -144,17 +162,20 @@ METHOD(shunt_manager_t, install, bool,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
this->shunts->insert_last(this->shunts, child->get_ref(child));
|
this->shunts->insert_last(this->shunts, child->get_ref(child));
|
||||||
|
this->installing++;
|
||||||
this->lock->unlock(this->lock);
|
this->lock->unlock(this->lock);
|
||||||
|
|
||||||
success = install_shunt_policy(child);
|
success = install_shunt_policy(child);
|
||||||
|
|
||||||
|
this->lock->write_lock(this->lock);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
this->lock->write_lock(this->lock);
|
|
||||||
this->shunts->remove(this->shunts, child, NULL);
|
this->shunts->remove(this->shunts, child, NULL);
|
||||||
this->lock->unlock(this->lock);
|
|
||||||
child->destroy(child);
|
child->destroy(child);
|
||||||
}
|
}
|
||||||
|
this->installing--;
|
||||||
|
this->condvar->signal(this->condvar);
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,18 +284,31 @@ METHOD(shunt_manager_t, create_enumerator, enumerator_t*,
|
|||||||
(void*)this->lock->unlock, this->lock);
|
(void*)this->lock->unlock, this->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(shunt_manager_t, destroy, void,
|
METHOD(shunt_manager_t, flush, void,
|
||||||
private_shunt_manager_t *this)
|
private_shunt_manager_t *this)
|
||||||
{
|
{
|
||||||
child_cfg_t *child;
|
child_cfg_t *child;
|
||||||
|
|
||||||
|
this->lock->write_lock(this->lock);
|
||||||
|
while (this->installing)
|
||||||
|
{
|
||||||
|
this->condvar->wait(this->condvar, this->lock);
|
||||||
|
}
|
||||||
while (this->shunts->remove_last(this->shunts, (void**)&child) == SUCCESS)
|
while (this->shunts->remove_last(this->shunts, (void**)&child) == SUCCESS)
|
||||||
{
|
{
|
||||||
uninstall_shunt_policy(child);
|
uninstall_shunt_policy(child);
|
||||||
child->destroy(child);
|
child->destroy(child);
|
||||||
}
|
}
|
||||||
this->shunts->destroy(this->shunts);
|
this->installing = INSTALL_DISABLED;
|
||||||
|
this->lock->unlock(this->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(shunt_manager_t, destroy, void,
|
||||||
|
private_shunt_manager_t *this)
|
||||||
|
{
|
||||||
|
this->shunts->destroy_offset(this->shunts, offsetof(child_cfg_t, destroy));
|
||||||
this->lock->destroy(this->lock);
|
this->lock->destroy(this->lock);
|
||||||
|
this->condvar->destroy(this->condvar);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,10 +324,12 @@ shunt_manager_t *shunt_manager_create()
|
|||||||
.install = _install,
|
.install = _install,
|
||||||
.uninstall = _uninstall,
|
.uninstall = _uninstall,
|
||||||
.create_enumerator = _create_enumerator,
|
.create_enumerator = _create_enumerator,
|
||||||
|
.flush = _flush,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.shunts = linked_list_create(),
|
.shunts = linked_list_create(),
|
||||||
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
|
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
|
||||||
|
.condvar = rwlock_condvar_create(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2015 Tobias Brunner
|
||||||
* Copyright (C) 2011 Andreas Steffen
|
* Copyright (C) 2011 Andreas Steffen
|
||||||
* HSR Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
@@ -55,6 +56,11 @@ struct shunt_manager_t {
|
|||||||
*/
|
*/
|
||||||
enumerator_t* (*create_enumerator)(shunt_manager_t *this);
|
enumerator_t* (*create_enumerator)(shunt_manager_t *this);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear any installed shunt.
|
||||||
|
*/
|
||||||
|
void (*flush)(shunt_manager_t *this);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a shunt_manager_t.
|
* Destroy a shunt_manager_t.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user