Compiling Python 3.6 on oldmary
In my never ending quest to run QRetail on less and less powerful hardware, on Saturday 8 June I pulled oldmary out of storage and compiled QRetail on it. Because it’s a 32 bit system I’m limited in my choice of Linux distribution. It’s currently running CentOS 6.9, version 6 being the last CentOS release to support 32 bit systems.
All went well until I tried to do something in that required the database. Then the Python MySQLdb module failed with the following error:
17:30:03.933 [ERROR] Exception! ProgrammingError: unsupported operand type(s) for %: 'bytes' and 'tuple' at MySQLdb/cursors.py line 203, in execute: 203 raise ProgrammingError(str(m)) called from bin/btiosql.py line 365, in get_row_via_qr_keys: 365 cursor.execute(sql, query_values) called from bin/btiosql.py line 572, in opr_9_GetGE: 572 return get_row_via_qr_keys(bt_params, IGNORE_CACHE, KEY_GE, IGNORE_ID, 9) called from bin/btiosql.py line 986, in bt2sql2bt: 986 elif opr==9: st,fcb,key,qr_data = opr_9_GetGE(bt_params) # GETGTEQ / START (uses index) called from bin/btiosql.py line 1084, in handler_loop: 1084 st = bt2sql2bt(db, qrd2sql, p_data, pipe_fn)
This is a bug I’ve hit before (see [Issues in Python MySQLdb].) It’s an edge
case involving Python 3.4 and version 1.4.2.post1 of MySQLdb/cusrsors.py.
The approppriate response is to upgrade Python. Unfortunately none of the later Python versions—3.5, 3.6, or 3.7—are available from the CentOS 6 repositories. So I decided to have a go at downloading the source code for Python 3.6 and building it from scratch.
The configure process ran with no problems, but the build process failed when
it called the python program it had just built and it died on an illegal
instruction. Running the program under a debugger quickly turned up the culprit
line in Include/pyatomic.h:
112 static __inline__ void 113 _Py_atomic_signal_fence(_Py_memory_order order) 114 { 115 if (order != _Py_memory_order_relaxed) 116 __asm__ volatile("":::"memory"); 117 } 118 119 static __inline__ void 120 _Py_atomic_thread_fence(_Py_memory_order order) 121 { 122 if (order != _Py_memory_order_relaxed) 123 __asm__ volatile("mfence":::"memory"); /* FAILS HERE */ 124 } 125
According to an entry on StackOverflow, the “mfence” part isn’t needed on x86 procesors.