88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.180 2008/01/01 19:45:52 momjian Exp $
11+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.181 2008/02/02 22:26:17 tgl Exp $
1212 *
1313 * NOTES
1414 * A lock table is a shared memory hash table. When
@@ -1102,16 +1102,17 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
11021102{
11031103 LOCKMETHODID lockmethodid = LOCALLOCK_LOCKMETHOD (* locallock );
11041104 LockMethod lockMethodTable = LockMethods [lockmethodid ];
1105- const char * old_status ;
1106- char * new_status = NULL ;
1107- int len ;
1105+ char * volatile new_status = NULL ;
11081106
11091107 LOCK_PRINT ("WaitOnLock: sleeping on lock" ,
11101108 locallock -> lock , locallock -> tag .mode );
11111109
11121110 /* Report change to waiting status */
11131111 if (update_process_title )
11141112 {
1113+ const char * old_status ;
1114+ int len ;
1115+
11151116 old_status = get_ps_display (& len );
11161117 new_status = (char * ) palloc (len + 8 + 1 );
11171118 memcpy (new_status , old_status , len );
@@ -1132,38 +1133,62 @@ WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
11321133 * that a cancel/die interrupt will interrupt ProcSleep after someone else
11331134 * grants us the lock, but before we've noticed it. Hence, after granting,
11341135 * the locktable state must fully reflect the fact that we own the lock;
1135- * we can't do additional work on return. Contrariwise, if we fail, any
1136- * cleanup must happen in xact abort processing, not here, to ensure it
1137- * will also happen in the cancel/die case.
1136+ * we can't do additional work on return.
1137+ *
1138+ * We can and do use a PG_TRY block to try to clean up after failure,
1139+ * but this still has a major limitation: elog(FATAL) can occur while
1140+ * waiting (eg, a "die" interrupt), and then control won't come back here.
1141+ * So all cleanup of essential state should happen in LockWaitCancel,
1142+ * not here. We can use PG_TRY to clear the "waiting" status flags,
1143+ * since doing that is unimportant if the process exits.
11381144 */
1145+ PG_TRY ();
1146+ {
1147+ if (ProcSleep (locallock , lockMethodTable ) != STATUS_OK )
1148+ {
1149+ /*
1150+ * We failed as a result of a deadlock, see CheckDeadLock().
1151+ * Quit now.
1152+ */
1153+ awaitedLock = NULL ;
1154+ LOCK_PRINT ("WaitOnLock: aborting on lock" ,
1155+ locallock -> lock , locallock -> tag .mode );
1156+ LWLockRelease (LockHashPartitionLock (locallock -> hashcode ));
11391157
1140- if (ProcSleep (locallock , lockMethodTable ) != STATUS_OK )
1158+ /*
1159+ * Now that we aren't holding the partition lock, we can give an
1160+ * error report including details about the detected deadlock.
1161+ */
1162+ DeadLockReport ();
1163+ /* not reached */
1164+ }
1165+ }
1166+ PG_CATCH ();
11411167 {
1142- /*
1143- * We failed as a result of a deadlock, see CheckDeadLock(). Quit now.
1144- */
1145- awaitedLock = NULL ;
1146- LOCK_PRINT ("WaitOnLock: aborting on lock" ,
1147- locallock -> lock , locallock -> tag .mode );
1148- LWLockRelease (LockHashPartitionLock (locallock -> hashcode ));
1168+ /* In this path, awaitedLock remains set until LockWaitCancel */
11491169
1150- /*
1151- * Now that we aren't holding the partition lock, we can give an error
1152- * report including details about the detected deadlock.
1153- */
1154- DeadLockReport ();
1155- /* not reached */
1170+ /* Report change to non-waiting status */
1171+ pgstat_report_waiting (false);
1172+ if (update_process_title )
1173+ {
1174+ set_ps_display (new_status , false);
1175+ pfree (new_status );
1176+ }
1177+
1178+ /* and propagate the error */
1179+ PG_RE_THROW ();
11561180 }
1181+ PG_END_TRY ();
11571182
11581183 awaitedLock = NULL ;
11591184
11601185 /* Report change to non-waiting status */
1186+ pgstat_report_waiting (false);
11611187 if (update_process_title )
11621188 {
11631189 set_ps_display (new_status , false);
11641190 pfree (new_status );
11651191 }
1166- pgstat_report_waiting (false);
11671192
11681193 LOCK_PRINT ("WaitOnLock: wakeup on lock" ,
11691194 locallock -> lock , locallock -> tag .mode );
0 commit comments