From b4564a98fa6ba4c93f3d1fe49909eb170650a888 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Tue, 27 Jan 1998 15:35:30 +0000 Subject: [PATCH] Deadlock ceallnup. (void) change for aix and hp compilers. protocol cleanup. --- src/backend/parser/parse_func.c | 6 ++--- src/backend/postmaster/postmaster.c | 4 ++-- src/backend/storage/lmgr/lock.c | 34 ++++++++++++++++++++++++----- src/include/access/heapam.h | 6 ++--- src/include/c.h | 14 ++++++++++-- src/include/config.h.in | 2 -- src/include/libpq/pqcomm.h | 10 ++++++--- src/man/lock.l | 8 ++++++- 8 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index d864dfc1f6..52efa3d396 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.8 1998/01/20 22:11:55 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.9 1998/01/27 15:34:39 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -728,7 +728,7 @@ func_get_detail(char *funcname, funcname); elog(NOTICE, "that satisfies the given argument types. you will have to"); elog(NOTICE, "retype your query using explicit typecasts."); - func_error("func_get_detail", funcname, nargs, oid_array); + func_error("", funcname, nargs, oid_array); } else { @@ -758,7 +758,7 @@ func_get_detail(char *funcname, elog(ERROR, "no such attribute or function \"%s\"", funcname); } - func_error("func_get_detail", funcname, nargs, oid_array); + func_error("", funcname, nargs, oid_array); } else { diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 940047b1e6..8b25be20df 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.71 1998/01/27 03:11:46 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.72 1998/01/27 15:34:43 momjian Exp $ * * NOTES * @@ -473,7 +473,7 @@ pmdaemonize(void) int i; if (fork()) - exit(0); + _exit(0); /* GH: If there's no setsid(), we hopefully don't need silent mode. * Until there's a better solution. */ diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 286824e27f..a509050704 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -7,12 +7,12 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.22 1998/01/27 03:00:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.23 1998/01/27 15:34:49 momjian Exp $ * * NOTES * Outside modules can create a lock table and acquire/release * locks. A lock table is a shared memory hash table. When - * a process tries to acquire a lock of a type that conflicts + * a process tries to acquire a lock of a type that conflictRs * with existing locks, it is put to sleep using the routines * in storage/lmgr/proc.c. * @@ -39,6 +39,7 @@ #include "postgres.h" #include "miscadmin.h" #include "storage/shmem.h" +#include "storage/sinvaladt.h" #include "storage/spin.h" #include "storage/proc.h" #include "storage/lock.h" @@ -1415,7 +1416,8 @@ LockingDisabled() * * This code takes a list of locks a process holds, and the lock that * the process is sleeping on, and tries to find if any of the processes - * waiting on its locks hold the lock it is waiting for. + * waiting on its locks hold the lock it is waiting for. If no deadlock + * is found, it goes on to look at all the processes waiting on their locks. * * We have already locked the master lock before being called. */ @@ -1427,7 +1429,16 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check) XIDLookupEnt *tmp = NULL; SHMEM_OFFSET end = MAKE_OFFSET(lockQueue); LOCK *lock; + static PROC* checked_procs[MaxBackendId]; + static int nprocs; + if (skip_check) + { + /* initialize at start of recursion */ + checked_procs[0] = MyProc; + nprocs = 1; + } + if (SHMQueueEmpty(lockQueue)) return false; @@ -1457,18 +1468,29 @@ DeadLockCheck(SHM_QUEUE *lockQueue, LOCK *findlock, bool skip_check) */ if (lock == findlock && !skip_check) return true; - else if (lock != findlock || !skip_check) + + /* + * No sense in looking at the wait queue of the lock we are + * looking for as it is MyProc's lock entry. + * If lock == findlock, and I got here, skip_check must be true. + */ + if (lock != findlock) { PROC_QUEUE *waitQueue = &(lock->waitProcs); PROC *proc; int i; + int j; proc = (PROC *) MAKE_PTR(waitQueue->links.prev); for (i = 0; i < waitQueue->size; i++) { - /* prevent endless loops */ - if (proc != MyProc && skip_check) + for (j = 0; j < nprocs; j++) + if (checked_procs[j] == proc) + break; + if (j >= nprocs) { + checked_procs[nprocs++] = proc; + Assert(nprocs <= MaxBackendId); /* If we found a deadlock, we can stop right now */ if (DeadLockCheck(&(proc->lockQueue), findlock, false)) return true; diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index cb9765c6d5..3e6e868780 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: heapam.h,v 1.24 1998/01/25 05:04:21 scrappy Exp $ + * $Id: heapam.h,v 1.25 1998/01/27 15:35:18 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -101,10 +101,10 @@ typedef HeapAccessStatisticsData *HeapAccessStatistics; #define heap_getattr(tup, b, attnum, tupleDesc, isnull) \ (AssertMacro((tup) != NULL) ? \ ((attnum) > (int) (tup)->t_natts) ? \ - (((isnull) ? (*(isnull) = true) : (void)NULL), (Datum)NULL) : \ + (((isnull) ? (*(isnull) = true) : dummyretNULL), (Datum)NULL) : \ ((attnum) > 0) ? \ fastgetattr((tup), (attnum), (tupleDesc), (isnull)) : \ - (((isnull) ? (*(isnull) = false) : (void)NULL), heap_getsysattr((tup), (b), (attnum))) : \ + (((isnull) ? (*(isnull) = false) : dummyretNULL), heap_getsysattr((tup), (b), (attnum))) : \ (Datum)NULL) extern HeapAccessStatistics heap_access_stats; /* in stats.c */ diff --git a/src/include/c.h b/src/include/c.h index 549f3481a6..d031f814e4 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -7,7 +7,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: c.h,v 1.29 1998/01/26 01:41:49 scrappy Exp $ + * $Id: c.h,v 1.30 1998/01/27 15:35:00 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -181,8 +181,18 @@ typedef char *Pointer; #endif /* !HAVE_ANSI_CPP */ +#ifndef __GNUC__ /* GNU cc */ +#endif + #ifndef __GNUC__ /* GNU cc */ #define inline +/* + * dummyret is used to set return values in macros that use ?: to make + * assignments. gcc wants these to be void, other compilers like char + */ +#define dummyret char +#else +#define dummyret void #endif #if defined(NEED_STD_HDRS) @@ -693,7 +703,7 @@ typedef struct Exception */ /* we do this so if the macro is used in an if action, it will work */ #define StrNCpy(dst,src,len) \ - (strncpy((dst),(src),(len)),(len > 0) ? *((dst)+(len)-1)='\0' : (void)NULL,(void)(dst)) + (strncpy((dst),(src),(len)),(len > 0) ? *((dst)+(len)-1)='\0' : (dummyret)NULL,(void)(dst)) /* Get a bit mask of the bits set in non-int32 aligned addresses */ #define INT_ALIGN_MASK (sizeof(int32) - 1) diff --git a/src/include/config.h.in b/src/include/config.h.in index 9c0b1829c1..521790528f 100644 --- a/src/include/config.h.in +++ b/src/include/config.h.in @@ -216,8 +216,6 @@ extern void srandom(int seed); * number of seconds. * We don't check for deadlocks just before sleeping because a deadlock is * a rare event, and checking is an expensive operation. - * We only detect deadlocks between two processes, not three or more, but - * these are the most common. */ #define DEADLOCK_CHECK_TIMER 60 diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h index 2a34459433..b3b67f8b73 100644 --- a/src/include/libpq/pqcomm.h +++ b/src/include/libpq/pqcomm.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: pqcomm.h,v 1.20 1998/01/27 04:08:28 momjian Exp $ + * $Id: pqcomm.h,v 1.21 1998/01/27 15:35:22 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -35,8 +35,12 @@ typedef union SockAddr { #define UNIXSOCK_PATH(sun,port) \ (sprintf((sun).sun_path, "/tmp/.s.PGSQL.%d", (port)) + \ - sizeof ((sun).sun_len) + sizeof ((sun).sun_family)) - + + 1 + sizeof ((sun).sun_family)) +/* + * + 1 is for BSD-specific sizeof((sun).sun_len) + * We never actually set sun_len, and I can't think of a + * platform-safe way of doing it, but the code still works. bjm + */ /* * These manipulate the frontend/backend protocol version number. diff --git a/src/man/lock.l b/src/man/lock.l index 8882cf15fb..0f2060dd5e 100644 --- a/src/man/lock.l +++ b/src/man/lock.l @@ -1,6 +1,6 @@ .\" This is -*-nroff-*- .\" XXX standard disclaimer belongs here.... -.\" $Header: /cvsroot/pgsql/src/man/Attic/lock.l,v 1.1 1998/01/23 06:01:36 momjian Exp $ +.\" $Header: /cvsroot/pgsql/src/man/Attic/lock.l,v 1.2 1998/01/27 15:35:30 momjian Exp $ .TH FETCH SQL 01/23/93 PostgreSQL PostgreSQL .SH NAME lock - exclusive lock a table @@ -17,6 +17,12 @@ inside a transaction. If you don't exclusive lock the table before the and do their own \fBupdate\fP, causing a deadlock while you both wait for the other to release the \fBselect\fP-induced shared lock so you can get an exclusive lock to do the \fBupdate.\fP +.PP +Another example of deadlock is where one user locks one table, and +another user locks a second table. While both keep their existing +locks, the first user tries to lock the second user's table, and the +second user tries to lock the first user's table. Both users deadlock +waiting for the tables to become available. .SH EXAMPLES .nf --