Bug #74742 mysql-connector-python 2.0.2 inconvenient exception handling
Submitted: 7 Nov 2014 20:24 Modified: 10 Nov 2014 9:54
Reporter: Andrew Garner Email Updates:
Status: Verified Impact on me:
None 
Category:Connector / Python Severity:S3 (Non-critical)
Version:2.0.2 OS:Any
Assigned to: CPU Architecture:Any

[7 Nov 2014 20:24] Andrew Garner
Description:
mysql-python-connector 2.0 is trapping all exceptions in various places due to a bare except catch all.  This occurs in at least the mysql/connector/connection.py:is_connected(), ping() and cmd_change_user() methods.  I ran into headaches here in the cursor() -> is_connected() path.

The exception handling here can end up swallowing a KeyboardInterrupt  exception and making pretty error handling difficult.

How to repeat:
Trigger a KeyboardInterrupt during an is_connected() check and see the exception swallowed.

Suggested fix:
I ran into this primarily in the cursor() -> is_connected() code path where I see the implementation is:

    def is_connected(self):
        """Reports whether the connection to MySQL Server is available

        This method checks whether the connection to MySQL is available.
        It is similar to ping(), but unlike the ping()-method, either True
        or False is returned and no exception is raised.

        Returns True or False.
        """
        try:
            self.cmd_ping()
        except:
            return False  # This method does not raise
        return True

The suggested fix is to not use a bare except but restrict the exceptions to those commonly raised by cmd_ping() - or at the very least reraise KeyboardInterrupt/SystemExit as needed.
[7 Nov 2014 20:44] Andrew Garner
Here is a traceback for a simple reproduction of this bug:
$ cat interrupt.py
import os
import mysql.connector

c = mysql.connector.connect(option_files=[os.path.expanduser('~/.my.cnf')])
while True:
    z = c.cursor()

$ python interrupt.py
^CTraceback (most recent call last):
  File "interrupt.py", line 6, in <module>
    z = c.cursor()
  File "/usr/lib/python2.6/site-packages/mysql/connector/connection.py", line 1383, in cursor
    raise errors.OperationalError("MySQL Connection not available.")
mysql.connector.errors.OperationalError: MySQL Connection not available.

Here I would rather except to see a KeyboardInterrupt.   And I do most times, of course, it all depends on where the code is when SIGINT is caught.

Tested on CentOS 6.6 with mysql-connector-python-2.0.2-1.el6.noarch from the mysql community yum repo.
[10 Nov 2014 9:54] Umesh Shastry
Hello Andrew Garner,

Thank you for the report.

Thanks,
Umesh
[10 Nov 2014 9:54] Umesh Shastry
// on OL6
 
[root@cluster-repo setups]# python
Python 2.6.6 (r266:84292, Jan 22 2014, 01:49:05)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import os
>>> import mysql.connector
>>> c = mysql.connector.connect(option_files=[os.path.expanduser('~/.my.cnf')])
>>> while True:
...     z = c.cursor()
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/mysql/connector/connection.py", line 1383, in cursor
mysql.connector.errors.OperationalError: MySQL Connection not available.

[root@cluster-repo setups]# rpm -qa|grep mysql-connector
mysql-connector-python-commercial-2.0.2-1.el6.noarch
[root@cluster-repo setups]#
[root@cluster-repo setups]# python --version
Python 2.6.6