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{
11031103LOCKMETHODID lockmethodid = LOCALLOCK_LOCKMETHOD (* locallock );
11041104LockMethod lockMethodTable = LockMethods [lockmethodid ];
1105- const char * old_status ;
1106- char * new_status = NULL ;
1107- int len ;
1105+ char * volatile new_status = NULL ;
11081106
11091107LOCK_PRINT ("WaitOnLock: sleeping on lock" ,
11101108locallock -> lock ,locallock -> tag .mode );
11111109
11121110/* Report change to waiting status */
11131111if (update_process_title )
11141112{
1113+ const char * old_status ;
1114+ int len ;
1115+
11151116old_status = get_ps_display (& len );
11161117new_status = (char * )palloc (len + 8 + 1 );
11171118memcpy (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
11581183awaitedLock = NULL ;
11591184
11601185/* Report change to non-waiting status */
1186+ pgstat_report_waiting (false);
11611187if (update_process_title )
11621188{
11631189set_ps_display (new_status , false);
11641190pfree (new_status );
11651191}
1166- pgstat_report_waiting (false);
11671192
11681193LOCK_PRINT ("WaitOnLock: wakeup on lock" ,
11691194locallock -> lock ,locallock -> tag .mode );