trap-manager: Make sure a config is not trapped twice

This commit is contained in:
Tobias Brunner
2013-10-17 10:23:32 +02:00
parent dd438ee22c
commit 6278e64230
+16 -4
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2011-2012 Tobias Brunner * Copyright (C) 2011-2013 Tobias Brunner
* Copyright (C) 2009 Martin Willi * Copyright (C) 2009 Martin Willi
* Hochschule fuer Technik Rapperswil * Hochschule fuer Technik Rapperswil
* *
@@ -19,6 +19,7 @@
#include <hydra.h> #include <hydra.h>
#include <daemon.h> #include <daemon.h>
#include <threading/rwlock.h> #include <threading/rwlock.h>
#include <threading/thread_value.h>
#include <collections/linked_list.h> #include <collections/linked_list.h>
@@ -61,6 +62,11 @@ struct private_trap_manager_t {
*/ */
rwlock_t *lock; rwlock_t *lock;
/**
* track if the current thread is installing a trap policy
*/
thread_value_t *installing;
/** /**
* listener to track acquiring IKE_SAs * listener to track acquiring IKE_SAs
*/ */
@@ -131,6 +137,7 @@ METHOD(trap_manager_t, install, u_int32_t,
} }
this->lock->write_lock(this->lock); this->lock->write_lock(this->lock);
this->installing->set(this->installing, this);
enumerator = this->traps->create_enumerator(this->traps); enumerator = this->traps->create_enumerator(this->traps);
while (enumerator->enumerate(enumerator, &entry)) while (enumerator->enumerate(enumerator, &entry))
{ {
@@ -143,7 +150,6 @@ METHOD(trap_manager_t, install, u_int32_t,
} }
} }
enumerator->destroy(enumerator); enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
if (found) if (found)
{ /* config might have changed so update everything */ { /* config might have changed so update everything */
@@ -188,11 +194,11 @@ METHOD(trap_manager_t, install, u_int32_t,
.child_sa = child_sa, .child_sa = child_sa,
.peer_cfg = peer->get_ref(peer), .peer_cfg = peer->get_ref(peer),
); );
this->lock->write_lock(this->lock);
this->traps->insert_last(this->traps, entry); this->traps->insert_last(this->traps, entry);
this->lock->unlock(this->lock);
reqid = child_sa->get_reqid(child_sa); reqid = child_sa->get_reqid(child_sa);
} }
this->installing->set(this->installing, NULL);
this->lock->unlock(this->lock);
if (status != SUCCESS) if (status != SUCCESS)
{ {
@@ -269,6 +275,10 @@ METHOD(trap_manager_t, find_reqid, u_int32_t,
entry_t *entry; entry_t *entry;
u_int32_t reqid = 0; u_int32_t reqid = 0;
if (this->installing->get(this->installing))
{ /* current thread holds the lock */
return reqid;
}
this->lock->read_lock(this->lock); this->lock->read_lock(this->lock);
enumerator = this->traps->create_enumerator(this->traps); enumerator = this->traps->create_enumerator(this->traps);
while (enumerator->enumerate(enumerator, &entry)) while (enumerator->enumerate(enumerator, &entry))
@@ -435,6 +445,7 @@ METHOD(trap_manager_t, destroy, void,
{ {
charon->bus->remove_listener(charon->bus, &this->listener.listener); charon->bus->remove_listener(charon->bus, &this->listener.listener);
this->traps->destroy_function(this->traps, (void*)destroy_entry); this->traps->destroy_function(this->traps, (void*)destroy_entry);
this->installing->destroy(this->installing);
this->lock->destroy(this->lock); this->lock->destroy(this->lock);
free(this); free(this);
} }
@@ -465,6 +476,7 @@ trap_manager_t *trap_manager_create(void)
}, },
.traps = linked_list_create(), .traps = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT), .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
.installing = thread_value_create(NULL),
); );
charon->bus->add_listener(charon->bus, &this->listener.listener); charon->bus->add_listener(charon->bus, &this->listener.listener);