[PATCH] Save/restore signal masks.

Nathaniel Smith njs at pobox.com
Wed May 5 04:40:00 UTC 2004


Attached for review.

This patch also overhauls a bit of the build system, so that testing
and such run out of the build directory, not the source directory;
this is necessitated by the addition of an impure module, that will
_only_ work from the build directory...

The goals of this patch, then, are:
  -- Signals aren't screwed up by threads.
  -- QMTest still builds fine on all systems.
  -- 'make check' still works on all systems.
  -- running out of the build directory still works on all systems.
  -- Building packages still works on all systems, except
     -- Packages are now architecture specific, and can only be
        built on the relevant architecture.

-- Nathaniel

-- 
"But in Middle-earth, the distinct accusative case disappeared from
the speech of the Noldor (such things happen when you are busy
fighting Orcs, Balrogs, and Dragons)."
-------------- next part --------------
? results.qmr
? qm/sigmask.c
? qm/external/__init__.pyc
? qm/external/__init__.pyo
? qmdist/command/bdist_wininst.py
? tests/regress/QMTest/regression_database.pyc
? tests/regress/QMTest/selftest.pyc
? tests/regress/tuple1/QMTest/tuple_test.pyc
? tests/results_files/QMTest/results_file_database.pyc
? tests/results_files/QMTest/results_file_test.pyc
? tests/xmldb/signals_unblocked.qmt
? tests/xmldb/signals_unblocked_tmpdir.qma
Index: ChangeLog
===================================================================
RCS file: /home/qm/Repository/qm/ChangeLog,v
retrieving revision 1.616
diff -u -r1.616 ChangeLog
--- ChangeLog	31 Mar 2004 10:32:44 -0000	1.616
+++ ChangeLog	5 May 2004 04:33:08 -0000
@@ -1,3 +1,22 @@
+2004-05-04  Nathaniel Smith  <njs at codesourcery.com>
+
+	* setup.py: Import 'Extension'.
+	Use it to build qm.sigmask.
+	* qm/sigmask.c: New file.
+	* qm/test/qmtest (main): Import 'qm.sigmask'; call
+	'qm.sigmask.save_mask'.
+	* qm/executable.py: Import 'qm.sigmask'.
+	(Executable._InitializeChild): Call 'qm.sigmask.restore_mask'.
+	
+	* tests/xmldb/signals_unblocked.qmt: New test.
+	* tests/xmldb/signals_unblocked_tmpdir.qma: New resource.
+	
+	* qmdist/command/check.py (check): Overhaul to respect
+	QMTESTFLAGS and use the correct path to the QMTest executable.
+	* GNUmakefile.in: Use "setup.py check" to run tests.
+	* qm/test/qmtest (rel_libdir): When running out of source tree,
+	use built library.	
+	
 2004-03-30  Nathaniel Smith  <njs at codesourcery.com>
 
 	* qm/common.py (htmllib): Import it.
Index: GNUmakefile.in
===================================================================
RCS file: /home/qm/Repository/qm/GNUmakefile.in,v
retrieving revision 1.34
diff -u -r1.34 GNUmakefile.in
--- GNUmakefile.in	24 Nov 2003 21:09:48 -0000	1.34
+++ GNUmakefile.in	5 May 2004 04:33:08 -0000
@@ -109,38 +109,13 @@
 check: check-serial check-threads check-processes
 
 check-serial: build
-	qm/test/qmtest -D tests run $(QMTESTFLAGS) \
-		-c qmtest_path=qm/test/qmtest
+	$(PYTHON) setup.py check --serial
 
 check-threads: build
-	rm -f tests/QMTest/thread_target
-	qm/test/qmtest -D tests create-target -a threads=4 \
-		-T tests/QMTest/thread_target \
-		thread thread_target.ThreadTarget
-	qm/test/qmtest -D tests run -T tests/QMTest/thread_target \
-		$(QMTESTFLAGS) \
-		-c qmtest_path=qm/test/qmtest \
-		-c qmtest_target=tests/QMTest/thread_target
+	$(PYTHON) setup.py check --threads
 
 check-processes: build
-	rm -f tests/QMTest/process_target
-	qm/test/qmtest -D tests create-target -a processes=4 \
-		-T tests/QMTest/process_target \
-		process process_target.ProcessTarget
-	qm/test/qmtest -D tests run -T tests/QMTest/process_target \
-		$(QMTESTFLAGS) \
-		-c qmtest_path=qm/test/qmtest \
-		-c qmtest_target=tests/QMTest/process_target
+	$(PYTHON) setup.py check --processes
 
 check-rsh: build
-	rm -f tests/QMTest/rsh_target
-	qm/test/qmtest -D tests create-target \
-                -a host=localhost -a remote_shell=ssh \
-		-T tests/QMTest/rsh_target \
-		rsh rsh_target.RSHTarget
-	qm/test/qmtest -D tests run -T tests/QMTest/rsh_target \
-		$(QMTESTFLAGS) \
-		-c qmtest_path=`pwd`/qm/test/qmtest \
-		-c qmtest_target=`pwd`/tests/QMTest/rsh_target
-
-
+	$(PYTHON) setup.py check --rsh
Index: setup.py
===================================================================
RCS file: /home/qm/Repository/qm/setup.py,v
retrieving revision 1.10
diff -u -r1.10 setup.py
--- setup.py	27 Feb 2004 22:04:33 -0000	1.10
+++ setup.py	5 May 2004 04:33:08 -0000
@@ -17,7 +17,7 @@
 # Imports
 ########################################################################
 
-from   distutils.core import setup
+from   distutils.core import setup, Extension
 import sys
 import os
 import os.path
@@ -94,6 +94,13 @@
 qmtest_py_script = qmtest_script + ".py"
 shutil.copyfile(qmtest_script, qmtest_py_script)
      
+# We need the sigmask extension on POSIX systems, but don't want it on
+# Win32.
+if sys.platform != "win32":
+    ext_modules = [Extension("qm.sigmask", ["qm/sigmask.c"])]
+else:
+    ext_modules = []
+
 setup(name="qm", 
       version=version,
       author="CodeSourcery, LLC",
@@ -116,6 +123,7 @@
                 'qm/test',
                 'qm/test/classes',
                 'qm/test/web'),
+      ext_modules=ext_modules,
       scripts=[qmtest_script, qmtest_py_script],
       data_files=[('qm/messages/test',
                    prefix(messages, 'qm/test/share/messages')),
Index: qm/executable.py
===================================================================
RCS file: /home/qm/Repository/qm/qm/executable.py,v
retrieving revision 1.24
diff -u -r1.24 executable.py
--- qm/executable.py	2 Mar 2004 03:24:41 -0000	1.24
+++ qm/executable.py	5 May 2004 04:33:08 -0000
@@ -38,6 +38,7 @@
     import cPickle
     import fcntl
     import select
+    import qm.sigmask
     
 ########################################################################
 # Classes
@@ -328,6 +329,8 @@
         This method is not used under Windows."""
 
         assert sys.platform != "win32"
+
+        qm.sigmask.restore_mask()
 
         if self.__dir:
             os.chdir(self.__dir)
Index: qm/test/qmtest
===================================================================
RCS file: /home/qm/Repository/qm/qm/test/qmtest,v
retrieving revision 1.3
diff -u -r1.3 qmtest
--- qm/test/qmtest	24 Nov 2003 06:35:01 -0000	1.3
+++ qm/test/qmtest	5 May 2004 04:33:08 -0000
@@ -54,7 +54,11 @@
 
 # Update sys.path so that we can find the rest of QMTest.
 if sys.platform != "win32":
-    rel_libdir = ""
+    # Following logic stolen from distutils.command.build:
+    import distutils.util
+    plat_spec = "lib.%s-%s" % (distutils.util.get_platform(),
+                               sys.version[0:3])
+    rel_libdir = os.path.join("build", plat_spec)
     """The relative path from the prefix to the library directory.
 
     This path gives the relative path from the prefix to the library
@@ -124,6 +128,11 @@
     
     # Make sure our Python is recent enough.
     check_python_version()
+
+    # Save the initial signal mask, as early as possible.
+    if sys.platform != "win32":
+        import qm.sigmask
+        qm.sigmask.save_mask()
 
     # Parse the command line.
     command = qm.test.cmdline.QMTest(sys.argv[1:], qm_path)
Index: qmdist/command/check.py
===================================================================
RCS file: /home/qm/Repository/qm/qmdist/command/check.py,v
retrieving revision 1.2
diff -u -r1.2 check.py
--- qmdist/command/check.py	14 Oct 2003 21:56:07 -0000	1.2
+++ qmdist/command/check.py	5 May 2004 04:33:08 -0000
@@ -52,6 +52,8 @@
         self.rsh = 0
         self.all = None
 
+        self.build_scripts = None
+
 
     def finalize_options (self):
         """Compute what tests to execute.
@@ -64,76 +66,88 @@
             self.threads = 1
             self.processes = 1
             self.rsh = 1
+        # Pick up the build scripts directory from the 'build' command.
+        self.set_undefined_options("build",
+                                   ("build_scripts", "build_scripts"))
 
 
-    qmtest = 'qm/test/qmtest'
-
-    def check_serial(self):
+    def check_serial(self, qmtest, options):
         """Perform serial tests."""
 
-        cmd = [check.qmtest,
-               '-D', 'tests', 'run', '-c',
-               norm('qmtest_path=qm/test/qmtest')]
+        cmd = [qmtest] + options + \
+              ['-D', 'tests', 'run', '-c',
+               norm('qmtest_path=' + qmtest)]
         spawn(cmd)
 
-    def check_threads(self):
+    def check_threads(self, qmtest, options):
         """Perform threaded tests."""
 
         remove_if_exists(norm('tests/QMTest/thread_target'))
-        cmd = [check.qmtest,
+        cmd = [qmtest,
                '-D', 'tests', 'create-target', '-a', 'threads=4',
                '-T', norm('tests/QMTest/thread_target'),
                'thread', 'thread_target.ThreadTarget']
         spawn(cmd)
-        cmd = [check.qmtest,
-               '-D', 'tests', 'run',
+        cmd = [qmtest] + options + \
+              ['-D', 'tests', 'run',
                '-T', norm('tests/QMTest/thread_target'),
-               '-c', 'qmtest_path=%s'%norm('qm/test/qmtest'),
+               '-c', 'qmtest_path=%s' % norm(qmtest),
                '-c', 'qmtest_target=%s'%norm('tests/QMTest/thread_target')]
         spawn(cmd)
 
-    def check_processes(self):
+    def check_processes(self, qmtest, options):
         """Perform sub-processed tests."""
 
         remove_if_exists(norm('tests/QMTest/process_target'))
-        cmd = [check.qmtest,
+        cmd = [qmtest,
                '-D', 'tests', 'create-target', '-a', 'processes=4',
                '-T', norm('tests/QMTest/process_target'),
                'process', 'process_target.ProcessTarget']
         spawn(cmd)
-        cmd = [check.qmtest,
-               '-D', 'tests', 'run',
+        cmd = [qmtest] + options + \
+              ['-D', 'tests', 'run',
                '-T', norm('tests/QMTest/process_target'),
-               '-c', 'qmtest_path=%s'%norm('qm/test/qmtest'),
+               '-c', 'qmtest_path=%s' % norm(qmtest),
                '-c', 'qmtest_target=%s'%norm('tests/QMTest/process_target')]
         spawn(cmd)
 
-    def check_rsh(self):
+    def check_rsh(self, qmtest, options):
         """Perform tests over a remote shell."""
 
         remove_if_exists(norm('tests/QMTest/rsh_target'))
-        cmd = [check.qmtest,
-               '-D', 'tests', 'create-target',
+        cmd = [qmtest,
+              '-D', 'tests', 'create-target',
                '-a', 'host=localhost', '-a', 'remote_shell=ssh',
                '-T', norm('tests/QMTest/rsh_target'),
                'rsh', 'rsh_target.RSHTarget']
         spawn(cmd)
-        cmd = [check.qmtest,
-               '-D', 'tests', 'run',
+        abs_target = os.path.abspath("tests/QMTest/rsh_target")
+        cmd = [qmtest] + options + \
+              ['-D', 'tests', 'run',
                '-T', norm('tests/QMTest/rsh_target'),
-               '-c', 'qmtest_path=%s'%norm('%s/qm/test/qmtest'%os.getcwd()),
-               '-c', 'qmtest_target=%s'%norm('%s/tests/QMTest/rsh_target'%os.getcwd())]
+               '-c', 'qmtest_path=%s' % norm(qmtest),
+               '-c', 'qmtest_target=%s' % norm(abs_target)]
         spawn(cmd)
 
 
     def run(self):
         """Execute the various tests."""
 
+        # Ensure that QMTest is already built.
+        self.run_command("build")
+
+        qmtest = os.path.abspath(os.path.join(self.build_scripts,
+                                              "qmtest"))
+        if os.environ.has_key("QMTESTFLAGS"):
+            options = os.environ["QMTESTFLAGS"].split()
+        else:
+            options = []
+
         if self.serial:
-            self.check_serial()
+            self.check_serial(qmtest, options)
         if self.threads:
-            self.check_threads()
+            self.check_threads(qmtest, options)
         if self.processes:
-            self.check_processes()
+            self.check_processes(qmtest, options)
         if self.rsh:
-            self.check_rsh()
+            self.check_rsh(qmtest, options)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: sigmask.c
Type: text/x-csrc
Size: 2176 bytes
Desc: not available
URL: <http://sourcerytools.com/pipermail/qmtest/attachments/20040504/0739d10f/attachment.c>
-------------- next part --------------
<?xml version="1.0" ?>
<!DOCTYPE extension
  PUBLIC '-//QM/2.2/Extension//EN'
  'http://www.codesourcery.com/qm/dtds/2.2/-//qm/2.2/extension//en.dtd'>
<extension class="command.ShellScriptTest" kind="test"><argument name="stdin"><text/></argument><argument name="stderr"><text/></argument><argument name="stdout"><text/></argument><argument name="prerequisites"><set/></argument><argument name="target_group"><text>.*</text></argument><argument name="exit_code"><integer>0</integer></argument><argument name="environment"><set/></argument><argument name="script"><text>if ! which cc >/dev/null; then
    echo "No cc, skipping test"
    exit 1
fi

cd $QMV_temp_dir_path

cat >check_sigmask.c <<EOF
#include <signal.h>

int main(int argc, char** argv)
{
    sigset_t s;
    sigprocmask(SIG_BLOCK, 0, &s);
    return (sigismember(&s, SIGTERM) || sigismember(&s, SIGXCPU));
}
EOF

cc check_sigmask.c -o check_sigmask

if ! ./check_sigmask; then
    echo "Test failed; some signals are blocked that shouldn't be."
    OUTCOME=1
else
    OUTCOME=0
fi

rm -f ./check_sigmask check_sigmask.c
exit $OUTCOME</text></argument><argument name="arguments"><set/></argument><argument name="timeout"><integer>-1</integer></argument><argument name="resources"><set><text>signals_unblocked_tmpdir</text></set></argument></extension>
-------------- next part --------------
<?xml version="1.0" ?>
<!DOCTYPE extension
  PUBLIC '-//QM/2.2/Extension//EN'
  'http://www.codesourcery.com/qm/dtds/2.2/-//qm/2.2/extension//en.dtd'>
<extension class="temporary.TempDirectoryResource" kind="resource"><argument name="dir_path_property"><text>temp_dir_path</text></argument><argument name="resources"><set/></argument><argument name="delete_recursively"><integer>1</integer></argument></extension>


More information about the qmtest mailing list