8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.445 2005/06/01 23:27:03 momjian Exp $
11
+ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.446 2005/06/02 21:03:24 tgl Exp $
12
12
*
13
13
* NOTES
14
14
* this is the "main" module of the postgres backend and
@@ -111,6 +111,13 @@ static volatile sig_atomic_t got_SIGHUP = false;
111
111
*/
112
112
static bool xact_started = false;
113
113
114
+ /*
115
+ * Flag to indicate that we are doing the outer loop's read-from-client,
116
+ * as opposed to any random read from client that might happen within
117
+ * commands like COPY FROM STDIN.
118
+ */
119
+ static bool DoingCommandRead = false;
120
+
114
121
/*
115
122
* Flags to implement skip-till-Sync-after-error behavior for messages of
116
123
* the extended query protocol.
@@ -406,6 +413,52 @@ ReadCommand(StringInfo inBuf)
406
413
return result ;
407
414
}
408
415
416
+ /*
417
+ * prepare_for_client_read -- set up to possibly block on client input
418
+ *
419
+ * This must be called immediately before any low-level read from the
420
+ * client connection. It is necessary to do it at a sufficiently low level
421
+ * that there won't be any other operations except the read kernel call
422
+ * itself between this call and the subsequent client_read_ended() call.
423
+ * In particular there mustn't be use of malloc() or other potentially
424
+ * non-reentrant libc functions. This restriction makes it safe for us
425
+ * to allow interrupt service routines to execute nontrivial code while
426
+ * we are waiting for input.
427
+ */
428
+ void
429
+ prepare_for_client_read (void )
430
+ {
431
+ if (DoingCommandRead )
432
+ {
433
+ /* Enable immediate processing of asynchronous signals */
434
+ EnableNotifyInterrupt ();
435
+ EnableCatchupInterrupt ();
436
+
437
+ /* Allow "die" interrupt to be processed while waiting */
438
+ ImmediateInterruptOK = true;
439
+
440
+ /* And don't forget to detect one that already arrived */
441
+ QueryCancelPending = false;
442
+ CHECK_FOR_INTERRUPTS ();
443
+ }
444
+ }
445
+
446
+ /*
447
+ * client_read_ended -- get out of the client-input state
448
+ */
449
+ void
450
+ client_read_ended (void )
451
+ {
452
+ if (DoingCommandRead )
453
+ {
454
+ ImmediateInterruptOK = false;
455
+ QueryCancelPending = false; /* forget any CANCEL signal */
456
+
457
+ DisableNotifyInterrupt ();
458
+ DisableCatchupInterrupt ();
459
+ }
460
+ }
461
+
409
462
410
463
/*
411
464
* Parse a query string and pass it through the rewriter.
@@ -2959,6 +3012,7 @@ PostgresMain(int argc, char *argv[], const char *username)
2959
3012
* not in other exception-catching places since these interrupts
2960
3013
* are only enabled while we wait for client input.
2961
3014
*/
3015
+ DoingCommandRead = false;
2962
3016
DisableNotifyInterrupt ();
2963
3017
DisableCatchupInterrupt ();
2964
3018
@@ -3063,21 +3117,13 @@ PostgresMain(int argc, char *argv[], const char *username)
3063
3117
}
3064
3118
3065
3119
/*
3066
- * (2) deal with pending asynchronous NOTIFY from other backends,
3067
- * and enable async.c's signal handler to execute NOTIFY directly.
3068
- * Then set up other stuff needed before blocking for input.
3120
+ * (2) Allow asynchronous signals to be executed immediately
3121
+ * if they come in while we are waiting for client input.
3122
+ * (This must be conditional since we don't want, say, reads on
3123
+ * behalf of COPY FROM STDIN doing the same thing.)
3069
3124
*/
3070
- QueryCancelPending = false; /* forget any earlier CANCEL
3071
- * signal */
3072
-
3073
- EnableNotifyInterrupt ();
3074
- EnableCatchupInterrupt ();
3075
-
3076
- /* Allow "die" interrupt to be processed while waiting */
3077
- ImmediateInterruptOK = true;
3078
- /* and don't forget to detect one that already arrived */
3079
- QueryCancelPending = false;
3080
- CHECK_FOR_INTERRUPTS ();
3125
+ QueryCancelPending = false; /* forget any earlier CANCEL signal */
3126
+ DoingCommandRead = true;
3081
3127
3082
3128
/*
3083
3129
* (3) read a command (loop blocks here)
@@ -3087,11 +3133,7 @@ PostgresMain(int argc, char *argv[], const char *username)
3087
3133
/*
3088
3134
* (4) disable async signal conditions again.
3089
3135
*/
3090
- ImmediateInterruptOK = false;
3091
- QueryCancelPending = false; /* forget any CANCEL signal */
3092
-
3093
- DisableNotifyInterrupt ();
3094
- DisableCatchupInterrupt ();
3136
+ DoingCommandRead = false;
3095
3137
3096
3138
/*
3097
3139
* (5) check for any other interesting events that happened while
0 commit comments