Merge branch 'bug-551'

This commit is contained in:
Daniele Varrazzo 2017-06-15 17:46:04 +01:00
commit 496cef80c4
3 changed files with 64 additions and 3 deletions

1
NEWS
View File

@ -18,6 +18,7 @@ What's new in psycopg 2.7.2
(:ticket:`#545`). (:ticket:`#545`).
- Fixed `~psycopg2.extras.ReplicationCursor.consume_stream()` - Fixed `~psycopg2.extras.ReplicationCursor.consume_stream()`
*keepalive_interval* argument (:ticket:`#547`). *keepalive_interval* argument (:ticket:`#547`).
- Fixed random `!SystemError` upon receiving abort signal (:ticket:`#551`).
- `~psycopg2.errorcodes` map updated to PostgreSQL 10 beta 1. - `~psycopg2.errorcodes` map updated to PostgreSQL 10 beta 1.

View File

@ -1893,8 +1893,12 @@ pq_fetch(cursorObject *curs, int no_result)
Dprintf("pq_fetch: pgstatus = %s", PQresStatus(pgstatus)); Dprintf("pq_fetch: pgstatus = %s", PQresStatus(pgstatus));
/* backend status message */ /* backend status message */
Py_XDECREF(curs->pgstatus); Py_CLEAR(curs->pgstatus);
curs->pgstatus = conn_text_from_chars(curs->conn, PQcmdStatus(curs->pgres)); if (!(curs->pgstatus = conn_text_from_chars(
curs->conn, PQcmdStatus(curs->pgres)))) {
ex = -1;
return ex;
}
switch(pgstatus) { switch(pgstatus) {

View File

@ -26,6 +26,7 @@ import os
import sys import sys
import time import time
import threading import threading
import subprocess as sp
from operator import attrgetter from operator import attrgetter
import psycopg2 import psycopg2
@ -33,7 +34,7 @@ import psycopg2.errorcodes
from psycopg2 import extensions as ext from psycopg2 import extensions as ext
from testutils import ( from testutils import (
unittest, decorate_all_tests, skip_if_no_superuser, script_to_py3, unittest, decorate_all_tests, skip_if_no_superuser,
skip_before_postgres, skip_after_postgres, skip_before_libpq, skip_before_postgres, skip_after_postgres, skip_before_libpq,
ConnectingTestCase, skip_if_tpc_disabled, skip_if_windows, slow) ConnectingTestCase, skip_if_tpc_disabled, skip_if_windows, slow)
@ -1516,6 +1517,61 @@ class PasswordLeakTestCase(ConnectingTestCase):
"user=someone password=xxx host=localhost dbname=nosuch") "user=someone password=xxx host=localhost dbname=nosuch")
class SignalTestCase(ConnectingTestCase):
@slow
def test_bug_551_returning(self):
# Raise an exception trying to decode 'id'
self._test_bug_551(query="""
INSERT INTO test551 (num) VALUES (%s) RETURNING id
""")
@slow
def test_bug_551_no_returning(self):
# Raise an exception trying to decode 'INSERT 0 1'
self._test_bug_551(query="""
INSERT INTO test551 (num) VALUES (%s)
""")
def _test_bug_551(self, query):
script = ("""\
import os
import sys
import time
import signal
import threading
import psycopg2
def handle_sigabort(sig, frame):
sys.exit(1)
def killer():
time.sleep(0.5)
os.kill(os.getpid(), signal.SIGABRT)
signal.signal(signal.SIGABRT, handle_sigabort)
conn = psycopg2.connect(%(dsn)r)
cur = conn.cursor()
cur.execute("create table test551 (id serial, num varchar(50))")
t = threading.Thread(target=killer)
t.daemon = True
t.start()
while True:
cur.execute(%(query)r, ("Hello, world!",))
""" % {'dsn': dsn, 'query': query})
proc = sp.Popen([sys.executable, '-c', script_to_py3(script)],
stdout=sp.PIPE, stderr=sp.PIPE)
(out, err) = proc.communicate()
self.assertNotEqual(proc.returncode, 0)
self.assert_(not err, err)
def test_suite(): def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__) return unittest.TestLoader().loadTestsFromName(__name__)