From 68c47befd4bc27b5691f457af48fa5028cf52286 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Thu, 19 Jun 2014 15:24:50 +0300
Subject: [PATCH 1/2] Fix bug in SQLCancel().

If one thread was busy executing a savepoint statement, while another thread
calls SQLCancel() on the statement, SQLCancel() would try to release the
locks held by the other thread. That's extremely racy; if the other thread
tries to increment/decrement the lock_CC_for_rb counter at the same time,
we could end up releasing the lock to many times or too few times. Also,
releasing a pthread mutex from a different thread than the one who acquired
it is undefined behavior.

AFAICS the DiscardStatementSvp() call in SQLCancel() can be safely removed.
It's outright wrong and dangerous if the statement is busy executing in
a different thread, and the other codepaths in PGAPI_Cancel() already call
DiscardStatementSvp().

Bug report by Jade Koskela.
---
 odbcapi.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/odbcapi.c b/odbcapi.c
index b5b5aac..9210cc5 100644
--- a/odbcapi.c
+++ b/odbcapi.c
@@ -103,14 +103,10 @@ SQLBindCol(HSTMT StatementHandle,
 RETCODE		SQL_API
 SQLCancel(HSTMT StatementHandle)
 {
-	RETCODE	ret;
-	StatementClass	*stmt = (StatementClass *) StatementHandle;
-
 	mylog("[SQLCancel]");
 	/* Not that neither ENTER_STMT_CS nor StartRollbackState is called */
 	/* SC_clear_error((StatementClass *) StatementHandle); maybe this neither */
-	ret = PGAPI_Cancel(StatementHandle);
-	return DiscardStatementSvp(stmt, ret, FALSE);
+	return PGAPI_Cancel(StatementHandle);
 }
 
 static BOOL theResultIsEmpty(const StatementClass *stmt)
-- 
2.0.0

