|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.195 2007/10/24 20:55:36 alvherre Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.196 2007/10/26 20:45:10 alvherre Exp $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
@@ -734,6 +734,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
734 | 734 | PROC_QUEUE *waitQueue = &(lock->waitProcs); |
735 | 735 | LOCKMASK myHeldLocks = MyProc->heldLocks; |
736 | 736 | bool early_deadlock = false; |
| 737 | + bool allow_autovacuum_cancel = true; |
737 | 738 | int myWaitStatus; |
738 | 739 | PGPROC *proc; |
739 | 740 | int i; |
@@ -893,6 +894,48 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable) |
893 | 894 | */ |
894 | 895 | myWaitStatus = MyProc->waitStatus; |
895 | 896 |
|
| 897 | + /* |
| 898 | + * If we are not deadlocked, but are waiting on an autovacuum-induced |
| 899 | + * task, send a signal to interrupt it. |
| 900 | + */ |
| 901 | + if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel) |
| 902 | + { |
| 903 | + PGPROC *autovac = GetBlockingAutoVacuumPgproc(); |
| 904 | + |
| 905 | + LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE); |
| 906 | + |
| 907 | + /* |
| 908 | + * Only do it if the worker is not working to protect against Xid |
| 909 | + * wraparound. |
| 910 | + */ |
| 911 | + if ((autovac != NULL) && |
| 912 | + (autovac->vacuumFlags & PROC_IS_AUTOVACUUM) && |
| 913 | + !(autovac->vacuumFlags & PROC_VACUUM_FOR_WRAPAROUND)) |
| 914 | + { |
| 915 | + int pid = autovac->pid; |
| 916 | + |
| 917 | + elog(DEBUG2, "sending cancel to blocking autovacuum pid = %d", |
| 918 | + pid); |
| 919 | + |
| 920 | + /* don't hold the lock across the kill() syscall */ |
| 921 | + LWLockRelease(ProcArrayLock); |
| 922 | + |
| 923 | + /* send the autovacuum worker Back to Old Kent Road */ |
| 924 | + if (kill(pid, SIGINT) < 0) |
| 925 | + { |
| 926 | + /* Just a warning to allow multiple callers */ |
| 927 | + ereport(WARNING, |
| 928 | + (errmsg("could not send signal to process %d: %m", |
| 929 | + pid))); |
| 930 | + } |
| 931 | + } |
| 932 | + else |
| 933 | + LWLockRelease(ProcArrayLock); |
| 934 | + |
| 935 | + /* prevent signal from being resent more than once */ |
| 936 | + allow_autovacuum_cancel = false; |
| 937 | + } |
| 938 | + |
896 | 939 | /* |
897 | 940 | * If awoken after the deadlock check interrupt has run, and |
898 | 941 | * log_lock_waits is on, then report about the wait. |
@@ -1189,13 +1232,16 @@ CheckDeadLock(void) |
1189 | 1232 | * RemoveFromWaitQueue took care of waking up any such processes. |
1190 | 1233 | */ |
1191 | 1234 | } |
1192 | | - else if (log_lock_waits) |
| 1235 | + else if (log_lock_waits || deadlock_state == DS_BLOCKED_BY_AUTOVACUUM) |
1193 | 1236 | { |
1194 | 1237 | /* |
1195 | 1238 | * Unlock my semaphore so that the interrupted ProcSleep() call can |
1196 | 1239 | * print the log message (we daren't do it here because we are inside |
1197 | 1240 | * a signal handler). It will then sleep again until someone |
1198 | 1241 | * releases the lock. |
| 1242 | + * |
| 1243 | + * If blocked by autovacuum, this wakeup will enable ProcSleep to send |
| 1244 | + * the cancelling signal to the autovacuum worker. |
1199 | 1245 | */ |
1200 | 1246 | PGSemaphoreUnlock(&MyProc->sem); |
1201 | 1247 | } |
|
0 commit comments