diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index eaf0491933dd568feda5c79b2c0467955c756f4c..8259b759e71b57214c0bd8b9e82f3e9cdb4b5828 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -13,7 +13,7 @@
  *
  *	Copyright (c) 2001-2008, PostgreSQL Global Development Group
  *
- *	$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.169 2008/01/01 19:45:51 momjian Exp $
+ *	$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.170 2008/03/21 21:08:31 tgl Exp $
  * ----------
  */
 #include "postgres.h"
@@ -2036,6 +2036,80 @@ pgstat_read_current_status(void)
 }
 
 
+/* ----------
+ * pgstat_get_backend_current_activity() -
+ *
+ *	Return a string representing the current activity of the backend with
+ *	the specified PID.  This looks directly at the BackendStatusArray,
+ *	and so will provide current information regardless of the age of our
+ *	transaction's snapshot of the status array.
+ *
+ *	It is the caller's responsibility to invoke this only for backends whose
+ *	state is expected to remain stable while the result is in use.  The
+ *	only current use is in deadlock reporting, where we can expect that
+ *	the target backend is blocked on a lock.  (There are corner cases
+ *	where the target's wait could get aborted while we are looking at it,
+ *	but the very worst consequence is to return a pointer to a string
+ *	that's been changed, so we won't worry too much.)
+ *
+ *	Note: return strings for special cases match pg_stat_get_backend_activity.
+ * ----------
+ */
+const char *
+pgstat_get_backend_current_activity(int pid)
+{
+	PgBackendStatus *beentry;
+	int			i;
+
+	beentry = BackendStatusArray;
+	for (i = 1; i <= MaxBackends; i++)
+	{
+		/*
+		 * Although we expect the target backend's entry to be stable, that
+		 * doesn't imply that anyone else's is.  To avoid identifying the
+		 * wrong backend, while we check for a match to the desired PID we
+		 * must follow the protocol of retrying if st_changecount changes
+		 * while we examine the entry, or if it's odd.  (This might be
+		 * unnecessary, since fetching or storing an int is almost certainly
+		 * atomic, but let's play it safe.)  We use a volatile pointer here
+		 * to ensure the compiler doesn't try to get cute.
+		 */
+		volatile PgBackendStatus *vbeentry = beentry;
+		bool	found;
+
+		for (;;)
+		{
+			int			save_changecount = vbeentry->st_changecount;
+
+			found = (vbeentry->st_procpid == pid);
+
+			if (save_changecount == vbeentry->st_changecount &&
+				(save_changecount & 1) == 0)
+				break;
+
+			/* Make sure we can break out of loop if stuck... */
+			CHECK_FOR_INTERRUPTS();
+		}
+
+		if (found)
+		{
+			/* Now it is safe to use the non-volatile pointer */
+			if (!superuser() && beentry->st_userid != GetUserId())
+				return "<insufficient privilege>";
+			else if (*(beentry->st_activity) == '\0')
+				return "<command string not enabled>";
+			else
+				return beentry->st_activity;
+		}
+
+		beentry++;
+	}
+
+	/* If we get here, caller is in error ... */
+	return "<backend information not available>";
+}
+
+
 /* ------------------------------------------------------------
  * Local support functions follow
  * ------------------------------------------------------------
diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c
index cad85e9d8a057b5a2e3ef763a93cb9edb47e7427..e1a66456f5429ea572167b21f661933e5e957969 100644
--- a/src/backend/storage/lmgr/deadlock.c
+++ b/src/backend/storage/lmgr/deadlock.c
@@ -12,7 +12,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.51 2008/01/01 19:45:52 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.52 2008/03/21 21:08:31 tgl Exp $
  *
  *	Interface:
  *
@@ -26,6 +26,7 @@
 #include "postgres.h"
 
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "storage/lmgr.h"
 #include "storage/proc.h"
 #include "utils/memutils.h"
@@ -878,12 +879,14 @@ PrintLockQueue(LOCK *lock, const char *info)
 void
 DeadLockReport(void)
 {
-	StringInfoData buf;
-	StringInfoData buf2;
+	StringInfoData detailbuf;
+	StringInfoData contextbuf;
+	StringInfoData locktagbuf;
 	int			i;
 
-	initStringInfo(&buf);
-	initStringInfo(&buf2);
+	initStringInfo(&detailbuf);
+	initStringInfo(&contextbuf);
+	initStringInfo(&locktagbuf);
 
 	for (i = 0; i < nDeadlockDetails; i++)
 	{
@@ -896,26 +899,36 @@ DeadLockReport(void)
 		else
 			nextpid = deadlockDetails[0].pid;
 
-		if (i > 0)
-			appendStringInfoChar(&buf, '\n');
+		/* reset locktagbuf to hold next object description */
+		resetStringInfo(&locktagbuf);
 
-		/* reset buf2 to hold next object description */
-		resetStringInfo(&buf2);
+		DescribeLockTag(&locktagbuf, &info->locktag);
 
-		DescribeLockTag(&buf2, &info->locktag);
+		if (i > 0)
+			appendStringInfoChar(&detailbuf, '\n');
 
-		appendStringInfo(&buf,
+		appendStringInfo(&detailbuf,
 				  _("Process %d waits for %s on %s; blocked by process %d."),
 						 info->pid,
 						 GetLockmodeName(info->locktag.locktag_lockmethodid,
 										 info->lockmode),
-						 buf2.data,
+						 locktagbuf.data,
 						 nextpid);
+
+		if (i > 0)
+			appendStringInfoChar(&contextbuf, '\n');
+
+		appendStringInfo(&contextbuf,
+						 _("Process %d: %s"),
+						 info->pid,
+						 pgstat_get_backend_current_activity(info->pid));
 	}
+
 	ereport(ERROR,
 			(errcode(ERRCODE_T_R_DEADLOCK_DETECTED),
 			 errmsg("deadlock detected"),
-			 errdetail("%s", buf.data)));
+			 errdetail("%s", detailbuf.data),
+			 errcontext("%s", contextbuf.data)));
 }
 
 /*
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 95589eb51e72b147866f95a30ad241b1a5924eb7..49fd149d55cbad82a130e031a19c4354443d07d9 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -5,7 +5,7 @@
  *
  *	Copyright (c) 2001-2008, PostgreSQL Global Development Group
  *
- *	$PostgreSQL: pgsql/src/include/pgstat.h,v 1.71 2008/01/01 19:45:56 momjian Exp $
+ *	$PostgreSQL: pgsql/src/include/pgstat.h,v 1.72 2008/03/21 21:08:31 tgl Exp $
  * ----------
  */
 #ifndef PGSTAT_H
@@ -507,6 +507,7 @@ extern void pgstat_bestart(void);
 extern void pgstat_report_activity(const char *what);
 extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
 extern void pgstat_report_waiting(bool waiting);
+extern const char *pgstat_get_backend_current_activity(int pid);
 
 extern void pgstat_initstats(Relation rel);