Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4db8718

Browse files
committed
Add SET statement_timeout capability. Timeout is in ms. A value of
zero turns off the timer.
1 parentccb3f90 commit4db8718

File tree

8 files changed

+200
-43
lines changed

8 files changed

+200
-43
lines changed

‎doc/src/sgml/runtime.sgml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.120 2002/07/05 01:17:20 momjian Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.121 2002/07/13 01:02:14 momjian Exp $
33
-->
44

55
<Chapter Id="runtime">
@@ -1584,6 +1584,16 @@ dynamic_library_path = '/usr/local/lib/postgresql:/home/my_project/lib:$libdir'
15841584
</listitem>
15851585
</varlistentry>
15861586

1587+
<varlistentry>
1588+
<term><varname>STATEMENT_TIMEOUT</varname> (<type>integer</type>)</term>
1589+
<listitem>
1590+
<para>
1591+
Aborts any statement that takes over the specified number of
1592+
microseconds. A value of zero turns off the timer.
1593+
</para>
1594+
</listitem>
1595+
</varlistentry>
1596+
15871597
<varlistentry>
15881598
<term><varname>SHARED_BUFFERS</varname> (<type>integer</type>)</term>
15891599
<listitem>

‎src/backend/postmaster/postmaster.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
*
3838
*
3939
* IDENTIFICATION
40-
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.280 2002/06/20 20:29:33 momjian Exp $
40+
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.281 2002/07/13 01:02:14 momjian Exp $
4141
*
4242
* NOTES
4343
*
@@ -2105,7 +2105,7 @@ DoBackend(Port *port)
21052105
* after a time delay, so that a broken client can't hog a connection
21062106
* indefinitely. PreAuthDelay doesn't count against the time limit.
21072107
*/
2108-
if (!enable_sigalrm_interrupt(AuthenticationTimeout*1000))
2108+
if (!enable_sig_alarm(AuthenticationTimeout*1000, false))
21092109
elog(FATAL,"DoBackend: Unable to set timer for auth timeout");
21102110

21112111
/*
@@ -2134,7 +2134,7 @@ DoBackend(Port *port)
21342134
* Done with authentication. Disable timeout, and prevent
21352135
* SIGTERM/SIGQUIT again until backend startup is complete.
21362136
*/
2137-
if (!disable_sigalrm_interrupt())
2137+
if (!disable_sig_alarm(false))
21382138
elog(FATAL,"DoBackend: Unable to disable timer for auth timeout");
21392139
PG_SETMASK(&BlockSig);
21402140

‎src/backend/storage/lmgr/proc.c

Lines changed: 155 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.121 2002/06/20 20:29:35 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.122 2002/07/13 01:02:14 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -52,8 +52,10 @@
5252
#include"storage/sinval.h"
5353
#include"storage/spin.h"
5454

55-
5655
intDeadlockTimeout=1000;
56+
intStatementTimeout=0;
57+
intRemainingStatementTimeout=0;
58+
boolalarm_is_statement_timeout= false;
5759

5860
PGPROC*MyProc=NULL;
5961

@@ -319,7 +321,7 @@ LockWaitCancel(void)
319321
waitingForLock= false;
320322

321323
/* Turn off the deadlock timer, if it's still running (see ProcSleep) */
322-
disable_sigalrm_interrupt();
324+
disable_sig_alarm(false);
323325

324326
/* Unlink myself from the wait queue, if on it (might not be anymore!) */
325327
LWLockAcquire(LockMgrLock,LW_EXCLUSIVE);
@@ -600,7 +602,7 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
600602

601603
/*
602604
* If we detected deadlock, give up without waiting. This must agree
603-
* withHandleDeadLock's recovery code, except that we shouldn't
605+
* withCheckDeadLock's recovery code, except that we shouldn't
604606
* release the semaphore since we haven't tried to lock it yet.
605607
*/
606608
if (early_deadlock)
@@ -632,13 +634,13 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
632634
* By delaying the check until we've waited for a bit, we can avoid
633635
* running the rather expensive deadlock-check code in most cases.
634636
*/
635-
if (!enable_sigalrm_interrupt(DeadlockTimeout))
637+
if (!enable_sig_alarm(DeadlockTimeout, false))
636638
elog(FATAL,"ProcSleep: Unable to set timer for process wakeup");
637639

638640
/*
639641
* If someone wakes us between LWLockRelease and PGSemaphoreLock,
640642
* PGSemaphoreLock will not block. The wakeup is "saved" by the
641-
* semaphore implementation. Note also that ifHandleDeadLock is
643+
* semaphore implementation. Note also that ifCheckDeadLock is
642644
* invoked but does not detect a deadlock, PGSemaphoreLock() will
643645
* continue to wait. There used to be a loop here, but it was useless
644646
* code...
@@ -654,7 +656,7 @@ ProcSleep(LOCKMETHODTABLE *lockMethodTable,
654656
/*
655657
* Disable the timer, if it's still running
656658
*/
657-
if (!disable_sigalrm_interrupt())
659+
if (!disable_sig_alarm(false))
658660
elog(FATAL,"ProcSleep: Unable to disable timer for process wakeup");
659661

660662
/*
@@ -785,7 +787,7 @@ ProcLockWakeup(LOCKMETHODTABLE *lockMethodTable, LOCK *lock)
785787
* --------------------
786788
*/
787789
void
788-
HandleDeadLock(SIGNAL_ARGS)
790+
CheckDeadLock(void)
789791
{
790792
intsave_errno=errno;
791793

@@ -921,52 +923,180 @@ ProcSendSignal(BackendId procId)
921923
* Delay is given in milliseconds.Caller should be sure a SIGALRM
922924
* signal handler is installed before this is called.
923925
*
926+
* This code properly handles multiple alarms when the statement_timeout
927+
* alarm is specified first.
928+
*
924929
* Returns TRUE if okay, FALSE on failure.
925930
*/
926931
bool
927-
enable_sigalrm_interrupt(intdelayms)
932+
enable_sig_alarm(intdelayms,boolis_statement_timeout)
928933
{
929934
#ifndef__BEOS__
930-
structitimervaltimeval,
931-
dummy;
935+
structitimervaltimeval,remaining;
936+
#else
937+
bigtime_ttime_interval,remaining;
938+
#endif
932939

940+
/* Don't set timer if the statement timeout scheduled before next alarm. */
941+
if (alarm_is_statement_timeout&&
942+
!is_statement_timeout&&
943+
RemainingStatementTimeout <=delayms)
944+
return true;
945+
946+
#ifndef__BEOS__
933947
MemSet(&timeval,0,sizeof(structitimerval));
934948
timeval.it_value.tv_sec=delayms /1000;
935949
timeval.it_value.tv_usec= (delayms %1000)*1000;
936-
if (setitimer(ITIMER_REAL,&timeval,&dummy))
950+
if (setitimer(ITIMER_REAL,&timeval,&remaining))
937951
return false;
938952
#else
939953
/* BeOS doesn't have setitimer, but has set_alarm */
940-
bigtime_ttime_interval;
941-
942954
time_interval=delayms*1000;/* usecs */
943-
if (set_alarm(time_interval,B_ONE_SHOT_RELATIVE_ALARM)<0)
955+
if ((remaining=set_alarm(time_interval,B_ONE_SHOT_RELATIVE_ALARM))<0)
944956
return false;
945957
#endif
946958

959+
if (is_statement_timeout)
960+
RemainingStatementTimeout=StatementTimeout;
961+
else
962+
{
963+
/* Switching to non-statement-timeout alarm, get remaining time */
964+
if (alarm_is_statement_timeout)
965+
{
966+
#ifndef__BEOS__
967+
/* We lose precision here because we convert to milliseconds */
968+
RemainingStatementTimeout=remaining.it_value.tv_sec*1000+
969+
remaining.it_value.tv_usec /1000;
970+
#else
971+
RemainingStatementTimeout=remaining /1000;
972+
#endif
973+
/* Rounding could cause a zero */
974+
if (RemainingStatementTimeout==0)
975+
RemainingStatementTimeout=1;
976+
}
977+
978+
if (RemainingStatementTimeout)
979+
{
980+
/* Remaining timeout alarm < delayms? */
981+
if (RemainingStatementTimeout <=delayms)
982+
{
983+
/* reinstall statement timeout alarm */
984+
alarm_is_statement_timeout= true;
985+
#ifndef__BEOS__
986+
remaining.it_value.tv_sec=RemainingStatementTimeout /1000;
987+
remaining.it_value.tv_usec= (RemainingStatementTimeout %1000)*1000;
988+
if (setitimer(ITIMER_REAL,&remaining,&timeval))
989+
return false;
990+
else
991+
return true;
992+
#else
993+
remaining=RemainingStatementTimeout*1000;
994+
if ((timeval=set_alarm(remaining,B_ONE_SHOT_RELATIVE_ALARM))<0)
995+
return false;
996+
else
997+
return true;
998+
#endif
999+
}
1000+
else
1001+
RemainingStatementTimeout-=delayms;
1002+
}
1003+
}
1004+
1005+
if (is_statement_timeout)
1006+
alarm_is_statement_timeout= true;
1007+
else
1008+
alarm_is_statement_timeout= false;
1009+
9471010
return true;
9481011
}
9491012

9501013
/*
951-
* Disable the SIGALRM interrupt, if it has not yet fired
1014+
* Cancel the SIGALRM timer.
1015+
*
1016+
* This is also called if the timer has fired to reschedule
1017+
* the statement_timeout timer.
9521018
*
9531019
* Returns TRUE if okay, FALSE on failure.
9541020
*/
9551021
bool
956-
disable_sigalrm_interrupt(void)
1022+
disable_sig_alarm(boolis_statement_timeout)
9571023
{
9581024
#ifndef__BEOS__
959-
structitimervaltimeval,
960-
dummy;
961-
1025+
structitimervaltimeval,remaining;
9621026
MemSet(&timeval,0,sizeof(structitimerval));
963-
if (setitimer(ITIMER_REAL,&timeval,&dummy))
964-
return false;
9651027
#else
966-
/* BeOS doesn't have setitimer, but has set_alarm */
967-
if (set_alarm(B_INFINITE_TIMEOUT,B_PERIODIC_ALARM)<0)
968-
return false;
1028+
bigtime_ttime_interval=0;
9691029
#endif
9701030

1031+
if (!is_statement_timeout&&RemainingStatementTimeout)
1032+
{
1033+
#ifndef__BEOS__
1034+
/* turn off timer and get remaining time, if any */
1035+
if (setitimer(ITIMER_REAL,&timeval,&remaining))
1036+
return false;
1037+
/* Add remaining time back because the timer didn't complete */
1038+
RemainingStatementTimeout+=remaining.it_value.tv_sec*1000+
1039+
remaining.it_value.tv_usec /1000;
1040+
/* Prepare to set timer */
1041+
timeval.it_value.tv_sec=RemainingStatementTimeout /1000;
1042+
timeval.it_value.tv_usec= (RemainingStatementTimeout %1000)*1000;
1043+
#else
1044+
/* BeOS doesn't have setitimer, but has set_alarm */
1045+
if ((time_interval=set_alarm(B_INFINITE_TIMEOUT,B_PERIODIC_ALARM))<0)
1046+
return false;
1047+
RemainingStatementTimeout+=time_interval /1000;
1048+
time_interval=RemainingStatementTimeout*1000;
1049+
#endif
1050+
/* Restore remaining statement timeout value */
1051+
alarm_is_statement_timeout= true;
1052+
}
1053+
/*
1054+
*Optimization: is_statement_timeout && RemainingStatementTimeout == 0
1055+
* does nothing. This is for cases where no timeout was set.
1056+
*/
1057+
if (!is_statement_timeout||RemainingStatementTimeout)
1058+
{
1059+
#ifndef__BEOS__
1060+
if (setitimer(ITIMER_REAL,&timeval,&remaining))
1061+
return false;
1062+
#else
1063+
if (time_interval)
1064+
{
1065+
if (set_alarm(time_interval,B_ONE_SHOT_RELATIVE_ALARM)<0)
1066+
return false;
1067+
}
1068+
else
1069+
{
1070+
if (set_alarm(B_INFINITE_TIMEOUT,B_PERIODIC_ALARM)<0)
1071+
return false;
1072+
}
1073+
#endif
1074+
}
1075+
1076+
if (is_statement_timeout)
1077+
RemainingStatementTimeout=0;
1078+
9711079
return true;
9721080
}
1081+
1082+
1083+
/*
1084+
* Call alarm handler, either StatementCancel or Deadlock checker.
1085+
*/
1086+
void
1087+
handle_sig_alarm(SIGNAL_ARGS)
1088+
{
1089+
if (alarm_is_statement_timeout)
1090+
{
1091+
RemainingStatementTimeout=0;
1092+
alarm_is_statement_timeout= false;
1093+
kill(MyProcPid,SIGINT);
1094+
}
1095+
else
1096+
{
1097+
CheckDeadLock();
1098+
/* Reactivate any statement_timeout alarm. */
1099+
disable_sig_alarm(false);
1100+
}
1101+
}
1102+

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp