implementation of lock detector

This commit is contained in:
roberto@goyle
2012-02-01 14:30:26 +01:00
parent 68a2902ce3
commit f9daec9e43
3 changed files with 87 additions and 6 deletions
+52 -4
View File
@@ -1,5 +1,31 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static void uwsgi_register_lock(void *ptr, int rw) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uli) {
uwsgi.registered_locks = uwsgi_malloc(sizeof(struct uwsgi_lock_item));
uwsgi.registered_locks->lock_ptr = ptr;
uwsgi.registered_locks->rw = rw;
uwsgi.registered_locks->next = NULL;
}
else {
while(uli) {
if (!uli->next) {
uli->next = uwsgi_malloc(sizeof(struct uwsgi_lock_item));
uli->next->lock_ptr = ptr;
uli->rw = rw;
uli->next->next = NULL;
return;
}
uli = uli->next;
}
}
}
#ifdef UWSGI_LOCK_USE_MUTEX
@@ -123,31 +149,53 @@ void uwsgi_unlock(void *lock) {
#ifdef UWSGI_LOCK_USE_OSX_SPINLOCK
#define UWSGI_LOCK_SIZE sizeof(OSSpinLock)
#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock)
#define UWSGI_LOCK_SIZE sizeof(OSSpinLock) + sizeof(pid_t)
#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock) + sizeof(pid_t)
void uwsgi_lock_init(void *lock) {
memset(lock, 0, sizeof(OSSpinLock));
memset(lock, 0, UWSGI_LOCK_SIZE);
uwsgi_register_lock(lock, 0);
}
void uwsgi_lock(void *lock) {
OSSpinLockLock((OSSpinLock *) lock);
pid_t *pid = (pid_t *) lock + sizeof(OSSpinLock);
*pid = uwsgi.mypid;
}
void uwsgi_unlock(void *lock) {
OSSpinLockUnlock((OSSpinLock *) lock);
pid_t *pid = (pid_t *) lock + sizeof(OSSpinLock);
*pid = 0;
}
pid_t uwsgi_lock_check(void *lock) {
if (OSSpinLockTry((OSSpinLock *) lock)) {
OSSpinLockUnlock((OSSpinLock *) lock);
return 0;
}
pid_t *pid = (pid_t *) lock + sizeof(OSSpinLock);
return *pid;
}
void uwsgi_rwlock_init(void *lock) {
memset(lock, 0, UWSGI_LOCK_SIZE);
uwsgi_register_lock(lock, 1);
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
pid_t uwsgi_rwlock_check(void *lock) { return uwsgi_lock_check(lock); }
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
#endif
+24 -2
View File
@@ -1538,11 +1538,33 @@ int master_loop(char **argv, char **environ) {
// now check for lb pool
continue;
}
if (diedpid > 0) {
// check for deadlocks first
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
while(uli) {
pid_t locked_pid = 0;
if (uli->rw) {
locked_pid = uwsgi_rwlock_check(uli->lock_ptr);
}
else {
locked_pid = uwsgi_lock_check(uli->lock_ptr);
}
if (locked_pid == diedpid) {
uwsgi_log("[deadlock-detector] pid %d was holding lock %p\n", (int) diedpid, uli->lock_ptr);
if (uli->rw) {
uwsgi_rwunlock(uli->lock_ptr);
}
else {
uwsgi_unlock(uli->lock_ptr);
}
}
uli = uli->next;
}
}
// reload gateways and daemons only on normal workflow
if (!uwsgi.to_heaven && !uwsgi.to_hell) {
+11
View File
@@ -289,6 +289,13 @@ struct uwsgi_string_list {
struct uwsgi_string_list *next;
};
struct uwsgi_lock_item {
void *lock_ptr;
int rw;
struct uwsgi_lock_item *next;
};
struct uwsgi_dyn_dict {
char *key;
@@ -1414,6 +1421,8 @@ struct uwsgi_server {
int cluster_fd;
struct sockaddr_in mc_cluster_addr;
struct uwsgi_lock_item *registered_locks;
int check_cache;
uint32_t cache_max_items;
@@ -1972,10 +1981,12 @@ char *uwsgi_cache_get(char *, uint16_t, uint64_t *);
uint32_t uwsgi_cache_exists(char *, uint16_t);
void uwsgi_lock_init(void *);
pid_t uwsgi_lock_check(void *);
void uwsgi_lock(void *);
void uwsgi_unlock(void *);
void uwsgi_rwlock_init(void *);
pid_t uwsgi_rwlock_check(void *);
void uwsgi_rlock(void *);
void uwsgi_wlock(void *);
void uwsgi_rwunlock(void *);