git » libfiu » commit 0d4f662

bindings/python: Write fiu_ctrl.py atomically

author Alberto Bertogli
2018-09-29 21:50:22 UTC
committer Alberto Bertogli
2018-09-30 21:50:42 UTC
parent 540515f78b6b05948f9b86be51e2639b505deca0

bindings/python: Write fiu_ctrl.py atomically

When doing a parallel build, we might run both python2 and python3
builds concurrently, causing a race in writing fiu_ctrl.py.

The race could result in installing a partially-written fiu_ctrl.py.

This patch fixes the race by doing an atomic "write to tmp + rename" to
generate fiu_ctrl.py.

This bug was reported by Adrian Bunk <bunk@debian.org>, and found by the
Debian reproducible builds project:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=909843

bindings/python/setup.py +9 -2

diff --git a/bindings/python/setup.py b/bindings/python/setup.py
index 6bb9c0b..963f613 100644
--- a/bindings/python/setup.py
+++ b/bindings/python/setup.py
@@ -1,6 +1,7 @@
 
 import os
 import sys
+import tempfile
 from distutils.core import setup, Extension
 from distutils.command.build_py import build_py
 
@@ -22,12 +23,18 @@ class generate_and_build_py (build_py):
         prefix = os.environ.get('PREFIX', '/usr/local/')
         plibpath = os.environ.get('PLIBPATH', prefix + '/lib/')
 
-        contents = open('fiu_ctrl.in.py', 'r').read()
+        contents = open('fiu_ctrl.in.py', 'rt').read()
         contents = contents.replace('@@PLIBPATH@@', plibpath)
 
-        out = open('fiu_ctrl.py', 'w')
+        # Create/update the file atomically, as this could be invoked in
+        # parallel for python 2 and 3, and we don't want to accidentally use
+        # partially written files.
+        out = tempfile.NamedTemporaryFile(
+                mode = 'wt', delete = False,
+                dir = '.', prefix = 'tmp-fiu_ctrl.py')
         out.write(contents)
         out.close()
+        os.rename(out.name, 'fiu_ctrl.py')
 
 
 fiu_ll = Extension("fiu_ll",