Hello all,

I've created a lock timeout patch and it's attached.

When a transaction is blocked by another transaction because of
waiting a lock, we need a lock timeout in some cases.

Using this patch, the lock timeout is enabled with
'lock_timeout = xxxx' directive in postgresql.conf,
and if a timeout is occured, an error code (40P02)
will be returned and a client application can detect it using

  JDBC: SQLException.getSQLState()
  C:    PQresultErrorField()

I know my code need to be cleaned up,
but any comments about this patch?

-- 
NAGAYASU Satoshi <[EMAIL PROTECTED]>

Index: backend/postmaster/postmaster.c
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/backend/postmaster/postmaster.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 postmaster.c
*** backend/postmaster/postmaster.c     10 Jun 2004 00:22:29 -0000      1.1.1.1
--- backend/postmaster/postmaster.c     18 Jun 2004 03:17:22 -0000
***************
*** 2418,2424 ****
         * after a time delay, so that a broken client can't hog a connection
         * indefinitely.  PreAuthDelay doesn't count against the time limit.
         */
!       if (!enable_sig_alarm(AuthenticationTimeout * 1000, false))
                elog(FATAL, "could not set timer for authorization timeout");
  
        /*
--- 2418,2424 ----
         * after a time delay, so that a broken client can't hog a connection
         * indefinitely.  PreAuthDelay doesn't count against the time limit.
         */
!       if (!enable_sig_alarm(AuthenticationTimeout * 1000, false, false))
                elog(FATAL, "could not set timer for authorization timeout");
  
        /*
***************
*** 2447,2453 ****
         * Done with authentication.  Disable timeout, and prevent
         * SIGTERM/SIGQUIT again until backend startup is complete.
         */
!       if (!disable_sig_alarm(false))
                elog(FATAL, "could not disable timer for authorization timeout");
        PG_SETMASK(&BlockSig);
  
--- 2447,2453 ----
         * Done with authentication.  Disable timeout, and prevent
         * SIGTERM/SIGQUIT again until backend startup is complete.
         */
!       if (!disable_sig_alarm(false, false))
                elog(FATAL, "could not disable timer for authorization timeout");
        PG_SETMASK(&BlockSig);
  
Index: backend/storage/lmgr/proc.c
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 proc.c
*** backend/storage/lmgr/proc.c 10 Jun 2004 00:22:29 -0000      1.1.1.1
--- backend/storage/lmgr/proc.c 28 Jun 2004 03:20:10 -0000
***************
*** 52,60 ****
--- 52,68 ----
  #include "storage/sinval.h"
  #include "storage/spin.h"
  
+ #ifdef LOCKTIMEOUT_DEBUG
+ #define PRINT_TIME(MSG, X) \
+         elog(NOTICE, "%s: %d.%03d", MSG, (X).tv_sec, ((X).tv_usec/1000))
+ #else
+ #define PRINT_TIME(MSG, X) {}
+ #endif
+ 
  /* GUC variables */
  int                   DeadlockTimeout = 1000;
  int                   StatementTimeout = 0;
+ int                   LockTimeout     = 0;
  
  /* Pointer to this process's PGPROC struct, if any */
  PGPROC           *MyProc = NULL;
***************
*** 78,92 ****
  /* Mark these volatile because they can be changed by signal handler */
  static volatile bool statement_timeout_active = false;
  static volatile bool deadlock_timeout_active = false;
  
  /* statement_fin_time is valid only if statement_timeout_active is true */
  static struct timeval statement_fin_time;
! 
  
  static void ProcKill(void);
  static void DummyProcKill(void);
  static bool CheckStatementTimeout(void);
  
  
  /*
   * Report number of semaphores needed by InitProcGlobal.
--- 86,102 ----
  /* Mark these volatile because they can be changed by signal handler */
  static volatile bool statement_timeout_active = false;
  static volatile bool deadlock_timeout_active = false;
+ static volatile bool lock_timeout_active = false;
  
  /* statement_fin_time is valid only if statement_timeout_active is true */
  static struct timeval statement_fin_time;
! static struct timeval lock_fin_time;
  
  static void ProcKill(void);
  static void DummyProcKill(void);
  static bool CheckStatementTimeout(void);
  
+ static LOCK *prevWaitLock = NULL;
  
  /*
   * Report number of semaphores needed by InitProcGlobal.
***************
*** 244,249 ****
--- 254,261 ----
        MyProc->waitHolder = NULL;
        SHMQueueInit(&(MyProc->procHolders));
  
+       prevWaitLock = NULL;
+ 
        /*
         * Arrange to clean up at backend exit.
         */
***************
*** 307,312 ****
--- 319,326 ----
        MyProc->waitHolder = NULL;
        SHMQueueInit(&(MyProc->procHolders));
  
+       prevWaitLock = NULL;
+ 
        /*
         * Arrange to clean up at process exit.
         */
***************
*** 338,344 ****
        waitingForLock = false;
  
        /* Turn off the deadlock timer, if it's still running (see ProcSleep) */
!       disable_sig_alarm(false);
  
        /* Unlink myself from the wait queue, if on it (might not be anymore!) */
        LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
--- 352,358 ----
        waitingForLock = false;
  
        /* Turn off the deadlock timer, if it's still running (see ProcSleep) */
!       disable_sig_alarm(false, false);
  
        /* Unlink myself from the wait queue, if on it (might not be anymore!) */
        LWLockAcquire(LockMgrLock, LW_EXCLUSIVE);
***************
*** 627,632 ****
--- 641,648 ----
  
        MyProc->errType = STATUS_OK;    /* initialize result for success */
  
+       prevWaitLock = MyProc->waitLock;
+ 
        /*
         * If we detected deadlock, give up without waiting.  This must agree
         * with CheckDeadLock's recovery code, except that we shouldn't
***************
*** 661,667 ****
         * By delaying the check until we've waited for a bit, we can avoid
         * running the rather expensive deadlock-check code in most cases.
         */
!       if (!enable_sig_alarm(DeadlockTimeout, false))
                elog(FATAL, "could not set timer for process wakeup");
  
        /*
--- 677,683 ----
         * By delaying the check until we've waited for a bit, we can avoid
         * running the rather expensive deadlock-check code in most cases.
         */
!       if (!enable_sig_alarm(DeadlockTimeout, false, false))
                elog(FATAL, "could not set timer for process wakeup");
  
        /*
***************
*** 683,689 ****
        /*
         * Disable the timer, if it's still running
         */
!       if (!disable_sig_alarm(false))
                elog(FATAL, "could not disable timer for process wakeup");
  
        /*
--- 699,705 ----
        /*
         * Disable the timer, if it's still running
         */
!       if (!disable_sig_alarm(false, false))
                elog(FATAL, "could not disable timer for process wakeup");
  
        /*
***************
*** 738,743 ****
--- 754,761 ----
        proc->waitHolder = NULL;
        proc->errType = errType;
  
+       prevWaitLock = NULL;
+ 
        /* And awaken it */
        PGSemaphoreUnlock(&proc->sem);
  
***************
*** 885,890 ****
--- 903,911 ----
         * RemoveFromWaitQueue took care of waking up any such processes.
         */
        LWLockRelease(LockMgrLock);
+ 
+       deadlock_timeout_active = false;
+       prevWaitLock = NULL;
  }
  
  
***************
*** 930,936 ****
                PGSemaphoreUnlock(&proc->sem);
  }
  
- 
  /*****************************************************************************
   * SIGALRM interrupt support
   *
--- 951,956 ----
***************
*** 949,955 ****
   * Returns TRUE if okay, FALSE on failure.
   */
  bool
! enable_sig_alarm(int delayms, bool is_statement_timeout)
  {
  #ifdef WIN32
  #warning add Win32 timer
--- 969,975 ----
   * Returns TRUE if okay, FALSE on failure.
   */
  bool
! enable_sig_alarm(int delayms, bool is_statement_timeout, bool is_lock_timeout)
  {
  #ifdef WIN32
  #warning add Win32 timer
***************
*** 963,970 ****
        bigtime_t       time_interval;
  #endif
  
        /* Compute target timeout time if we will need it */
!       if (is_statement_timeout || statement_timeout_active)
        {
                gettimeofday(&fin_time, NULL);
                fin_time.tv_sec += delayms / 1000;
--- 983,999 ----
        bigtime_t       time_interval;
  #endif
  
+ #ifdef LOCKTIMEOUT_DEBUG
+       elog(NOTICE, "enable_sig_alarm: is_statement_timeout=%d, "
+                "is_lock_timeout=%d\n",
+                is_statement_timeout,
+                is_lock_timeout);
+       elog(NOTICE, "enable_sig_alarm: LockTimeout=%d", LockTimeout);
+ #endif
+ 
        /* Compute target timeout time if we will need it */
!       if (is_statement_timeout || statement_timeout_active ||
!               is_lock_timeout || lock_timeout_active )
        {
                gettimeofday(&fin_time, NULL);
                fin_time.tv_sec += delayms / 1000;
***************
*** 974,979 ****
--- 1003,1009 ----
                        fin_time.tv_sec++;
                        fin_time.tv_usec -= 1000000;
                }
+               PRINT_TIME("enable_sig_alarm", fin_time);
        }
  
        if (is_statement_timeout)
***************
*** 983,1012 ****
                statement_fin_time = fin_time;
                statement_timeout_active = true;
        }
!       else if (statement_timeout_active)
        {
!               /*
!                * Begin deadlock timeout with statement-level timeout active
!                *
!                * Here, we want to interrupt at the closer of the two timeout times.
!                * If fin_time >= statement_fin_time then we need not touch the
!                * existing timer setting; else set up to interrupt at the
!                * deadlock timeout time.
!                *
!                * NOTE: in this case it is possible that this routine will be
!                * interrupted by the previously-set timer alarm.  This is okay
!                * because the signal handler will do only what it should do
!                * according to the state variables.  The deadlock checker may get
!                * run earlier than normal, but that does no harm.
!                */
!               deadlock_timeout_active = true;
!               if (fin_time.tv_sec > statement_fin_time.tv_sec ||
!                       (fin_time.tv_sec == statement_fin_time.tv_sec &&
!                        fin_time.tv_usec >= statement_fin_time.tv_usec))
!                       return true;
        }
        else
        {
                /* Begin deadlock timeout with no statement-level timeout */
                deadlock_timeout_active = true;
        }
--- 1013,1066 ----
                statement_fin_time = fin_time;
                statement_timeout_active = true;
        }
!       else if ( is_lock_timeout )
        {
!               Assert(!lock_timeout_active);
!               lock_fin_time = fin_time;
!               lock_timeout_active = true;
!               prevWaitLock = MyProc->waitLock;
        }
        else
        {
+               /*
+                * If is_statement_timeout and is_lock_timeout are false,
+                * delayms means a timeout time to detect deadlock.
+                */
+               if (statement_timeout_active)
+               {
+                       /*
+                        * Begin deadlock timeout with statement-level timeout active
+                        *
+                        * Here, we want to interrupt at the closer of the two timeout 
times.
+                        * If fin_time >= statement_fin_time then we need not touch the
+                        * existing timer setting; else set up to interrupt at the
+                        * deadlock timeout time.
+                        *
+                        * NOTE: in this case it is possible that this routine will be
+                        * interrupted by the previously-set timer alarm.  This is okay
+                        * because the signal handler will do only what it should do
+                        * according to the state variables.  The deadlock checker may 
get
+                        * run earlier than normal, but that does no harm.
+                        */
+                       deadlock_timeout_active = true;
+                       if (fin_time.tv_sec > statement_fin_time.tv_sec ||
+                               (fin_time.tv_sec == statement_fin_time.tv_sec &&
+                                fin_time.tv_usec >= statement_fin_time.tv_usec))
+                               return true;
+               }
+               if (lock_timeout_active)
+               {
+                       /*
+                        * If the lock timeout has been already set, and it is shorter
+                        * than me, there is no need to set another one.
+                        * The shortest timer has to be set.
+                        */
+                       deadlock_timeout_active = true;
+                       if (fin_time.tv_sec > lock_fin_time.tv_sec ||
+                               (fin_time.tv_sec == lock_fin_time.tv_sec &&
+                                fin_time.tv_usec >= lock_fin_time.tv_usec))
+                               return true;
+               }
                /* Begin deadlock timeout with no statement-level timeout */
                deadlock_timeout_active = true;
        }
***************
*** 1016,1021 ****
--- 1070,1086 ----
        MemSet(&timeval, 0, sizeof(struct itimerval));
        timeval.it_value.tv_sec = delayms / 1000;
        timeval.it_value.tv_usec = (delayms % 1000) * 1000;
+       {
+               PRINT_TIME("enable_sig_alarm", timeval.it_value);
+ #ifdef LOCKTIMEOUT_DEBUG
+               elog(NOTICE, "enable_sig_alarm: deadlock_timeout_active=%d, "
+                        "statement_timeout_active=%d, "
+                        "lock_timeout_active=%d\n",
+                        deadlock_timeout_active,
+                        statement_timeout_active,
+                        lock_timeout_active);
+ #endif
+       }
        if (setitimer(ITIMER_REAL, &timeval, NULL))
                return false;
  #else
***************
*** 1025,1030 ****
--- 1090,1098 ----
                return false;
  #endif
  #endif
+ 
+       PRINT_TIME("enable_sig_alarm: lock_fin_time", lock_fin_time);
+ 
        return true;
  }
  
***************
*** 1036,1042 ****
   * Returns TRUE if okay, FALSE on failure.
   */
  bool
! disable_sig_alarm(bool is_statement_timeout)
  {
  #ifdef WIN32
  #warning add Win32 timer
--- 1104,1110 ----
   * Returns TRUE if okay, FALSE on failure.
   */
  bool
! disable_sig_alarm(bool is_statement_timeout, bool is_lock_timeout)
  {
  #ifdef WIN32
  #warning add Win32 timer
***************
*** 1049,1055 ****
         *
         * We will re-enable the interrupt if necessary in CheckStatementTimeout.
         */
!       if (statement_timeout_active || deadlock_timeout_active)
        {
  #ifndef __BEOS__
                struct itimerval timeval;
--- 1117,1124 ----
         *
         * We will re-enable the interrupt if necessary in CheckStatementTimeout.
         */
!       if (statement_timeout_active || deadlock_timeout_active ||
!               lock_timeout_active )
        {
  #ifndef __BEOS__
                struct itimerval timeval;
***************
*** 1057,1070 ****
                MemSet(&timeval, 0, sizeof(struct itimerval));
                if (setitimer(ITIMER_REAL, &timeval, NULL))
                {
!                       statement_timeout_active = deadlock_timeout_active = false;
                        return false;
                }
  #else
                /* BeOS doesn't have setitimer, but has set_alarm */
                if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)
                {
!                       statement_timeout_active = deadlock_timeout_active = false;
                        return false;
                }
  #endif
--- 1126,1143 ----
                MemSet(&timeval, 0, sizeof(struct itimerval));
                if (setitimer(ITIMER_REAL, &timeval, NULL))
                {
!                       statement_timeout_active = deadlock_timeout_active
!                                       = lock_timeout_active = false;
!                       prevWaitLock = NULL;
                        return false;
                }
  #else
                /* BeOS doesn't have setitimer, but has set_alarm */
                if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)
                {
!                       statement_timeout_active = deadlock_timeout_active
!                                       = lock_timeout_active = false;
!                       prevWaitLock = NULL;
                        return false;
                }
  #endif
***************
*** 1076,1081 ****
--- 1149,1159 ----
        /* Cancel or reschedule statement timeout */
        if (is_statement_timeout)
                statement_timeout_active = false;
+       else if (is_lock_timeout)
+       {
+               lock_timeout_active = false;
+               prevWaitLock = NULL;
+       }
        else if (statement_timeout_active)
        {
                if (!CheckStatementTimeout())
***************
*** 1086,1091 ****
--- 1164,1196 ----
  }
  
  
+ static struct timeval *
+ GetShorterTimer(struct timeval *r, struct timeval t1, struct timeval t2)
+ {
+       if ( t1.tv_sec<t2.tv_sec )
+       {
+               r->tv_sec = t1.tv_sec;
+               r->tv_usec = t1.tv_usec;
+       }
+       else if ( t1.tv_sec>t2.tv_sec )
+       {
+               r->tv_sec = t2.tv_sec;
+               r->tv_usec = t2.tv_usec;
+       }
+       else if ( t1.tv_usec<t2.tv_usec )
+       {
+               r->tv_sec = t1.tv_sec;
+               r->tv_usec = t1.tv_usec;
+       }
+       else
+       {
+               r->tv_sec = t2.tv_sec;
+               r->tv_usec = t2.tv_usec;
+       }
+       return r;
+ }
+ 
+ 
  /*
   * Check for statement timeout.  If the timeout time has come,
   * trigger a query-cancel interrupt; if not, reschedule the SIGALRM
***************
*** 1121,1128 ****
                struct itimerval timeval;
  
                MemSet(&timeval, 0, sizeof(struct itimerval));
!               timeval.it_value.tv_sec = statement_fin_time.tv_sec - now.tv_sec;
!               timeval.it_value.tv_usec = statement_fin_time.tv_usec - now.tv_usec;
                if (timeval.it_value.tv_usec < 0)
                {
                        timeval.it_value.tv_sec--;
--- 1226,1242 ----
                struct itimerval timeval;
  
                MemSet(&timeval, 0, sizeof(struct itimerval));
! 
!               if ( statement_timeout_active && lock_timeout_active )
!                       GetShorterTimer(&(timeval.it_value), 
statement_fin_time,lock_fin_time);
!               else if ( statement_timeout_active )
!                       timeval.it_value = statement_fin_time;
!               else if ( lock_timeout_active )
!                       timeval.it_value = lock_fin_time;
!                       
!               timeval.it_value.tv_sec -= now.tv_sec;
!               timeval.it_value.tv_usec -= now.tv_usec;
! 
                if (timeval.it_value.tv_usec < 0)
                {
                        timeval.it_value.tv_sec--;
***************
*** 1131,1136 ****
--- 1245,1251 ----
                if (setitimer(ITIMER_REAL, &timeval, NULL))
                        return false;
  #else
+ #warning *** LOCKTIMEOUT NOT IMPLEMENTED!!! ***
                /* BeOS doesn't have setitimer, but has set_alarm */
                bigtime_t       time_interval;
  
***************
*** 1146,1151 ****
--- 1261,1346 ----
        return true;
  }
  
+ static bool
+ CheckLockTimeout(void)
+ {
+       struct timeval now;
+ 
+       if (!lock_timeout_active)
+               return true;                    /* do nothing if not active */
+ 
+       gettimeofday(&now, NULL);
+ 
+       PRINT_TIME("CheckLockTimeout: now", now);
+       PRINT_TIME("CheckLockTimeout: lock_fin_time", lock_fin_time);
+ 
+       if (now.tv_sec > lock_fin_time.tv_sec ||
+               (now.tv_sec == lock_fin_time.tv_sec &&
+                now.tv_usec >= lock_fin_time.tv_usec))
+ 
+       elog(DEBUG1, "MyProc.lwWaiting=%d, MyProc.lwExclusive=%d", MyProc->lwWaiting,
+                MyProc->lwWaiting);
+       elog(DEBUG1, "MyProc.waitLock=%p", MyProc->waitLock);
+ 
+       /*
+        * Still waiting a same lock.
+        */
+       if ( MyProc->waitLock && MyProc->waitLock==prevWaitLock )
+       {
+               /* Time to die */
+               lock_timeout_active = false;
+               prevWaitLock = NULL;
+               
+               ereport(ERROR, (errcode(ERRCODE_T_R_LOCKTIMEOUT_DETECTED),
+                               errmsg("the current transaction is going to be 
rolled-back because of lock timeout.")));
+       }
+       else
+       {
+               /* Not time yet, so (re)schedule the interrupt */
+ #ifdef WIN32
+ #warning add win32 timer
+ #else
+ #ifndef __BEOS__
+               struct itimerval timeval;
+ 
+               MemSet(&timeval, 0, sizeof(struct itimerval));
+ 
+               if ( statement_timeout_active && lock_timeout_active )
+                       GetShorterTimer(&(timeval.it_value), 
statement_fin_time,lock_fin_time);
+               else if ( statement_timeout_active )
+                       timeval.it_value = statement_fin_time;
+               else if ( lock_timeout_active )
+                       timeval.it_value = lock_fin_time;
+ 
+               PRINT_TIME("CheckLockTimeout: timeval.it_value", timeval.it_value);
+               timeval.it_value.tv_sec -= now.tv_sec;
+               timeval.it_value.tv_usec -= now.tv_usec;
+               PRINT_TIME("CheckLockTimeout: timeval.it_value", timeval.it_value);
+ 
+               if (timeval.it_value.tv_usec < 0)
+               {
+                       timeval.it_value.tv_sec--;
+                       timeval.it_value.tv_usec += 1000000;
+               }
+               if (setitimer(ITIMER_REAL, &timeval, NULL))
+                       return false;
+ #else
+ #warning *** NOT IMPLEMENTED!!! ***
+               /* BeOS doesn't have setitimer, but has set_alarm */
+               bigtime_t       time_interval;
+ 
+               time_interval =
+                       (lock_fin_time.tv_sec - now.tv_sec) * 1000000 +
+                       (lock_fin_time.tv_usec - now.tv_usec);
+               if (set_alarm(time_interval, B_ONE_SHOT_RELATIVE_ALARM) < 0)
+                       return false;
+ #endif
+ #endif
+       }
+ 
+       return true;
+ }
+ 
  
  /*
   * Signal handler for SIGALRM
***************
*** 1160,1173 ****
  {
        int                     save_errno = errno;
  
        if (deadlock_timeout_active)
        {
-               deadlock_timeout_active = false;
                CheckDeadLock();
        }
  
        if (statement_timeout_active)
                (void) CheckStatementTimeout();
  
        errno = save_errno;
  }
--- 1355,1382 ----
  {
        int                     save_errno = errno;
  
+ //    elog(NOTICE, "handle_sig_alarm: deadlock_timeout_active=%d, 
statement_timeout_active=%d, lock_timeout_active=%d", deadlock_timeout_active, 
statement_timeout_active, lock_timeout_active);
+ 
+       PRINT_TIME("handle_sig_alarm: lock_fin_time", lock_fin_time);
+ 
        if (deadlock_timeout_active)
        {
                CheckDeadLock();
        }
  
+       PRINT_TIME("handle_sig_alarm: lock_fin_time", lock_fin_time);
+ 
        if (statement_timeout_active)
+       {
                (void) CheckStatementTimeout();
+       }
+ 
+       PRINT_TIME("handle_sig_alarm: lock_fin_time", lock_fin_time);
+ 
+       if (lock_timeout_active)
+       {
+               (void) CheckLockTimeout();
+       }
  
        errno = save_errno;
  }
Index: backend/tcop/postgres.c
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/backend/tcop/postgres.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 postgres.c
*** backend/tcop/postgres.c     10 Jun 2004 00:22:29 -0000      1.1.1.1
--- backend/tcop/postgres.c     18 Jun 2004 03:16:32 -0000
***************
*** 1734,1740 ****
  
                /* Set statement timeout running, if any */
                if (StatementTimeout > 0)
!                       enable_sig_alarm(StatementTimeout, true);
  
                xact_started = true;
        }
--- 1734,1742 ----
  
                /* Set statement timeout running, if any */
                if (StatementTimeout > 0)
!                       enable_sig_alarm(StatementTimeout, true, false);
!               if (LockTimeout > 0)
!                       enable_sig_alarm(LockTimeout, false, true);
  
                xact_started = true;
        }
***************
*** 1749,1755 ****
                DeferredTriggerEndQuery();
  
                /* Cancel any active statement timeout before committing */
!               disable_sig_alarm(true);
  
                /* Now commit the command */
                ereport(DEBUG3,
--- 1751,1757 ----
                DeferredTriggerEndQuery();
  
                /* Cancel any active statement timeout before committing */
!               disable_sig_alarm(true, true);
  
                /* Now commit the command */
                ereport(DEBUG3,
***************
*** 2704,2710 ****
                QueryCancelPending = false;
                InterruptHoldoffCount = 1;
                CritSectionCount = 0;   /* should be unnecessary, but... */
!               disable_sig_alarm(true);
                QueryCancelPending = false;             /* again in case timeout 
occurred */
                DisableNotifyInterrupt();
                debug_query_string = NULL;
--- 2706,2712 ----
                QueryCancelPending = false;
                InterruptHoldoffCount = 1;
                CritSectionCount = 0;   /* should be unnecessary, but... */
!               disable_sig_alarm(true, true);
                QueryCancelPending = false;             /* again in case timeout 
occurred */
                DisableNotifyInterrupt();
                debug_query_string = NULL;
Index: backend/utils/misc/guc.c
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/backend/utils/misc/guc.c,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 guc.c
*** backend/utils/misc/guc.c    10 Jun 2004 00:22:33 -0000      1.1.1.1
--- backend/utils/misc/guc.c    28 Jun 2004 01:30:20 -0000
***************
*** 910,917 ****
                        NULL
                },
                &DeadlockTimeout,
!               1000, 0, INT_MAX, NULL, NULL
        },
  
  #ifdef HAVE_SYSLOG
        {
--- 910,927 ----
                        NULL
                },
                &DeadlockTimeout,
!               5000, 0, INT_MAX, NULL, NULL
        },
+ 
+       {
+               {"lock_timeout", PGC_SIGHUP, LOCK_MANAGEMENT,
+                       gettext_noop("The time in milliseconds to wait on lock before 
detecting timeout."),
+                       NULL
+               },
+               &LockTimeout,
+               0, 0, INT_MAX, NULL, NULL
+       },
+ 
  
  #ifdef HAVE_SYSLOG
        {
Index: include/storage/proc.h
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/include/storage/proc.h,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 proc.h
*** include/storage/proc.h      10 Jun 2004 00:22:34 -0000      1.1.1.1
--- include/storage/proc.h      15 Jun 2004 08:20:34 -0000
***************
*** 88,93 ****
--- 88,94 ----
  
  /* configurable options */
  extern int    DeadlockTimeout;
+ extern int    LockTimeout;
  extern int    StatementTimeout;
  
  
***************
*** 111,118 ****
  extern void ProcCancelWaitForSignal(void);
  extern void ProcSendSignal(BackendId procId);
  
! extern bool enable_sig_alarm(int delayms, bool is_statement_timeout);
! extern bool disable_sig_alarm(bool is_statement_timeout);
  extern void handle_sig_alarm(SIGNAL_ARGS);
  
  #endif   /* PROC_H */
--- 112,120 ----
  extern void ProcCancelWaitForSignal(void);
  extern void ProcSendSignal(BackendId procId);
  
! extern bool enable_sig_alarm(int delayms, bool is_statement_timeout,
!                                                        bool is_lock_timeout);
! extern bool disable_sig_alarm(bool is_statement_timeout, bool is_lock_timeout);
  extern void handle_sig_alarm(SIGNAL_ARGS);
  
  #endif   /* PROC_H */
Index: include/utils/errcodes.h
===================================================================
RCS file: /home/snaga/cvsroot/pgsql/src/include/utils/errcodes.h,v
retrieving revision 1.1.1.1
diff -c -r1.1.1.1 errcodes.h
*** include/utils/errcodes.h    10 Jun 2004 00:22:34 -0000      1.1.1.1
--- include/utils/errcodes.h    18 Jun 2004 06:29:09 -0000
***************
*** 203,208 ****
--- 203,211 ----
  #define ERRCODE_T_R_SERIALIZATION_FAILURE     MAKE_SQLSTATE('4','0', '0','0','1')
  #define ERRCODE_T_R_STATEMENT_COMPLETION_UNKNOWN      MAKE_SQLSTATE('4','0', 
'0','0','3')
  #define ERRCODE_T_R_DEADLOCK_DETECTED         MAKE_SQLSTATE('4','0', 'P','0','1')
+ #ifdef LOCKTIMEOUT
+  #define ERRCODE_T_R_LOCKTIMEOUT_DETECTED             MAKE_SQLSTATE('4','0', 
'P','0','2')
+ #endif
  
  /* Class 42 - Syntax Error or Access Rule Violation */
  #define ERRCODE_SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION         MAKE_SQLSTATE('4','2', 
'0','0','0')
---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to