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.