mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-08 06:31:58 +00:00
implementation of lock detector
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
Reference in New Issue
Block a user