Browse Source

[2297] use smp.forward_signal_enabled to detect SMP-support kernel on freebsd.

kern.smp.active is misleading because it's always defined and can return 0
on an SMP-support kernel
JINMEI Tatuya 12 years ago
parent
commit
7d777cee74

+ 13 - 3
src/lib/python/isc/sysinfo/sysinfo.py

@@ -389,9 +389,19 @@ class SysInfoFreeBSD(SysInfoFreeBSDOSX):
         super().__init__()
 
         try:
-            s = subprocess.check_output(['sysctl', '-n', 'kern.smp.active'])
-            self._platform_is_smp = int(s.decode('utf-8').strip()) > 0
-        except (subprocess.CalledProcessError, OSError):
+            # There doesn't seem to be an easy way to reliably detect whether
+            # the kernel was built with SMP support on FreeBSD.  We use
+            # a sysctl variable that is only defined in SMP kernels.
+            # This assumption seems to hold for recent several versions of
+            # FreeBSD, but it may not always be so for future versions.
+            s = subprocess.check_output(['sysctl', '-n',
+                                         'kern.smp.forward_signal_enabled'])
+            self._platform_is_smp = True # the value doesn't matter
+        except subprocess.CalledProcessError:
+            # if this variable isn't defined we should see this exception.
+            # intepret it as an indication of non-SMP kernel.
+            self._platform_is_smp = False
+        except OSError:
             pass
 
         try:

+ 31 - 4
src/lib/python/isc/sysinfo/tests/sysinfo_test.py

@@ -181,10 +181,13 @@ def _my_freebsd_osx_subprocess_check_output(command):
     else:
         return _my_bsd_subprocess_check_output(command)
 
-def _my_freebsd_subprocess_check_output(command):
+def _my_freebsd_subprocess_check_output(command, faked_output):
     assert type(command) == list, 'command argument is not a list'
-    if command == ['sysctl', '-n', 'kern.smp.active']:
-        return b'1\n'
+    if command == ['sysctl', '-n', 'kern.smp.forward_signal_enabled']:
+        output = faked_output['smp-sysctl']
+        if isinstance(output, Exception):
+            raise output
+        return faked_output['smp-sysctl']
     elif command == ['vmstat', '-H']:
         return b' procs    memory       page                    disks    traps          cpu\n r b w    avm     fre  flt  re  pi  po  fr  sr wd0 cd0  int   sys   cs us sy id\n 0 0 0   343434  123456   47   0   0   0   0   0   2   0    2    80   14  0  1 99\n'
     elif command == ['swapctl', '-s', '-k']:
@@ -379,13 +382,37 @@ class SysInfoTest(unittest.TestCase):
         # with mock ones for testing.
         platform.system = _my_freebsd_platform_system
         os.sysconf = _my_freebsd_os_sysconf
-        subprocess.check_output = _my_freebsd_subprocess_check_output
+
+        # We use a lambda object so we can tweak the subprocess output during
+        # the tests later.
+        faked_process_output = { 'smp-sysctl': b'1\n' }
+        subprocess.check_output = lambda command : \
+            _my_freebsd_subprocess_check_output(command, faked_process_output)
+
         os.uname = _my_freebsd_platform_uname
 
         s = SysInfoFromFactory()
         self.assertEqual(NPROCESSORS_FREEBSD, s.get_num_processors())
         self.assertTrue(s.get_platform_is_smp())
 
+        # We check the kernel SMP support by the availability of an sysctl
+        # variable.  The value (especiall a 0 value) shouldn't matter.
+        faked_process_output['smp-sysctl'] = b'0\n'
+        s = SysInfoFromFactory()
+        self.assertTrue(s.get_platform_is_smp())
+
+        # if the sysctl raises CalledProcessError, we treat it as non-SMP
+        # kernel.
+        faked_process_output['smp-sysctl'] = \
+            subprocess.CalledProcessError(1, 'sysctl')
+        s = SysInfoFromFactory()
+        self.assertFalse(s.get_platform_is_smp())
+
+        # if it results in OSError, no SMP information will be provided.
+        faked_process_output['smp-sysctl'] = OSError()
+        s = SysInfoFromFactory()
+        self.assertIsNone(s.get_platform_is_smp())
+
         self.check_bsd_values(s)
 
         self.assertEqual((0.2, 0.4, 0.6), s.get_loadavg())