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:
Tobias Brunner
2015-07-27 13:51:10 +02:00
parent 616ff9a236
commit bc36530670
2 changed files with 46 additions and 4 deletions
+40 -4
View File
@@ -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;
+6
View File
@@ -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.
*/ */