|
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