From b4564a98fa6ba4c93f3d1fe49909eb170650a888 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
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 d864dfc1f6d..52efa3d3960 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 940047b1e67..8b25be20df9 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 286824e27f6..a509050704a 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 cb9765c6d5a..3e6e8687805 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 549f3481a68..d031f814e45 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 9c0b1829c1f..521790528f6 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 2a344594331..b3b67f8b73b 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 8882cf15fb7..0f2060dd5e1 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
 --
-- 
GitLab