@@ -114,50 +114,38 @@ confirm_query_canceled_impl(int line, PGconn *conn)
114
114
PQconsumeInput (conn );
115
115
}
116
116
117
- #define send_cancellable_query (conn , monitorConn ) \
118
- send_cancellable_query_impl(__LINE__, conn, monitorConn)
117
+ /*
118
+ * Using monitorConn, query pg_stat_activity to see that the connection with
119
+ * the given PID is in the given state. We never stop until it does.
120
+ */
119
121
static void
120
- send_cancellable_query_impl (int line , PGconn * conn , PGconn * monitorConn )
122
+ wait_for_connection_state (int line , PGconn * monitorConn , int procpid , char * state )
121
123
{
122
- const char * env_wait ;
123
- const Oid paramTypes [1 ] = {INT4OID };
124
- int procpid = PQbackendPID (conn );
125
-
126
- env_wait = getenv ("PG_TEST_TIMEOUT_DEFAULT" );
127
- if (env_wait == NULL )
128
- env_wait = "180" ;
124
+ const Oid paramTypes [] = {INT4OID , TEXTOID };
125
+ const char * paramValues [2 ];
126
+ char * pidstr = psprintf ("%d" , procpid );
129
127
130
- if (PQsendQueryParams (conn , "SELECT pg_sleep($1)" , 1 , paramTypes ,
131
- & env_wait , NULL , NULL , 0 ) != 1 )
132
- pg_fatal_impl (line , "failed to send query: %s" , PQerrorMessage (conn ));
128
+ paramValues [0 ] = pidstr ;
129
+ paramValues [1 ] = state ;
133
130
134
- /*
135
- * Wait until the query is actually running. Otherwise sending a
136
- * cancellation request might not cancel the query due to race conditions.
137
- */
138
131
while (true)
139
132
{
140
- char * value ;
141
133
PGresult * res ;
142
- const char * paramValues [1 ];
143
- char pidval [16 ];
144
-
145
- snprintf (pidval , 16 , "%d" , procpid );
146
- paramValues [0 ] = pidval ;
134
+ char * value ;
147
135
148
136
res = PQexecParams (monitorConn ,
149
137
"SELECT count(*) FROM pg_stat_activity WHERE "
150
- "pid = $1 AND state = 'active' " ,
151
- 1 , NULL , paramValues , NULL , NULL , 1 );
138
+ "pid = $1 AND state = $2 " ,
139
+ 2 , paramTypes , paramValues , NULL , NULL , 1 );
152
140
153
141
if (PQresultStatus (res ) != PGRES_TUPLES_OK )
154
- pg_fatal ( "could not query pg_stat_activity: %s" , PQerrorMessage (monitorConn ));
142
+ pg_fatal_impl ( line , "could not query pg_stat_activity: %s" , PQerrorMessage (monitorConn ));
155
143
if (PQntuples (res ) != 1 )
156
- pg_fatal ( "unexpected number of rows received: %d" , PQntuples (res ));
144
+ pg_fatal_impl ( line , "unexpected number of rows received: %d" , PQntuples (res ));
157
145
if (PQnfields (res ) != 1 )
158
- pg_fatal ( "unexpected number of columns received: %d" , PQnfields (res ));
146
+ pg_fatal_impl ( line , "unexpected number of columns received: %d" , PQnfields (res ));
159
147
value = PQgetvalue (res , 0 , 0 );
160
- if (* value != '0' )
148
+ if (value [ 0 ] != '0' )
161
149
{
162
150
PQclear (res );
163
151
break ;
@@ -167,6 +155,38 @@ send_cancellable_query_impl(int line, PGconn *conn, PGconn *monitorConn)
167
155
/* wait 10ms before polling again */
168
156
pg_usleep (10000 );
169
157
}
158
+
159
+ pfree (pidstr );
160
+ }
161
+
162
+ #define send_cancellable_query (conn , monitorConn ) \
163
+ send_cancellable_query_impl(__LINE__, conn, monitorConn)
164
+ static void
165
+ send_cancellable_query_impl (int line , PGconn * conn , PGconn * monitorConn )
166
+ {
167
+ const char * env_wait ;
168
+ const Oid paramTypes [1 ] = {INT4OID };
169
+
170
+ /*
171
+ * Wait for the connection to be idle, so that our check for an active
172
+ * connection below is reliable, instead of possibly seeing an outdated
173
+ * state.
174
+ */
175
+ wait_for_connection_state (line , monitorConn , PQbackendPID (conn ), "idle" );
176
+
177
+ env_wait = getenv ("PG_TEST_TIMEOUT_DEFAULT" );
178
+ if (env_wait == NULL )
179
+ env_wait = "180" ;
180
+
181
+ if (PQsendQueryParams (conn , "SELECT pg_sleep($1)" , 1 , paramTypes ,
182
+ & env_wait , NULL , NULL , 0 ) != 1 )
183
+ pg_fatal_impl (line , "failed to send query: %s" , PQerrorMessage (conn ));
184
+
185
+ /*
186
+ * Wait for the query to start, because if the query is not running yet
187
+ * the cancel request that we send won't have any effect.
188
+ */
189
+ wait_for_connection_state (line , monitorConn , PQbackendPID (conn ), "active" );
170
190
}
171
191
172
192
/*
0 commit comments