From 142c1ad0891b3d97dfae4f0ae376617189905a17 Mon Sep 17 00:00:00 2001
From: Guido Trotter <ultrotter@google.com>
Date: Wed, 19 Oct 2011 18:28:42 +0100
Subject: [PATCH] Revert "utils.cfunc: Cleanup, more flexibility"

We discussed that this is not needed right now, and it breaks existing
functionality and unittests.

This reverts commit 6915fe26da8dce41fc967d761f005390aa956161.

Signed-off-by: Guido Trotter <ultrotter@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>
---
 Makefile.am                                   |  2 +-
 lib/utils/cfunc.py                            | 73 +++++++------------
 ...test.py => ganeti.utils.cfunc_unittest.py} |  4 +-
 3 files changed, 32 insertions(+), 47 deletions(-)
 rename test/{ganeti.utils.cfunc.mlockall_unittest.py => ganeti.utils.cfunc_unittest.py} (97%)

diff --git a/Makefile.am b/Makefile.am
index 5031a5303..2a513f15f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -724,7 +724,7 @@ python_tests = \
 	test/ganeti.tools.ensure_dirs_unittest.py \
 	test/ganeti.uidpool_unittest.py \
 	test/ganeti.utils.algo_unittest.py \
-	test/ganeti.utils.cfunc.mlockall_unittest.py \
+	test/ganeti.utils.cfunc_unittest.py \
 	test/ganeti.utils.filelock_unittest.py \
 	test/ganeti.utils.hash_unittest.py \
 	test/ganeti.utils.io_unittest.py \
diff --git a/lib/utils/cfunc.py b/lib/utils/cfunc.py
index a1b3af49b..ea14d6848 100644
--- a/lib/utils/cfunc.py
+++ b/lib/utils/cfunc.py
@@ -34,61 +34,44 @@ except ImportError:
   ctypes = None
 
 
-# Flags for mlockall(2) (from bits/mman.h)
+# Flags for mlockall() (from bits/mman.h)
 _MCL_CURRENT = 1
 _MCL_FUTURE = 2
 
 
-class _FuncWrapper:
-  def __init__(self, ct):
-    """Initializes this class.
-
-    """
-    # Make use of a dlopen(3) feature whereby giving a NULL handle returns the
-    # main program. Functions from all previously loaded libraries can then be
-    # used.
-    mainprog = ct.CDLL(None)
-
-    # The ctypes module before Python 2.6 does not have built-in functionality
-    # to access the global errno global (which, depending on the libc and build
-    # options, is per-thread), where function error codes are stored. Use GNU
-    # libc's way to retrieve errno(3) instead.
-    try:
-      errno_loc = getattr(mainprog, "__errno_location")
-    except AttributeError, err:
-      logging.debug("Unable to find errno location: %s", err)
-      errno_fn = None
-    else:
-      errno_loc.restype = ct.POINTER(ct.c_int)
-      errno_fn = lambda: errno_loc().contents.value
-
-    self.errno_fn = errno_fn
-
-    # Try to get mlockall(2)
-    self.mlockall_fn = getattr(mainprog, "mlockall", None)
-
-
 def Mlockall(_ctypes=ctypes):
   """Lock current process' virtual address space into RAM.
 
-  This is equivalent to the C call C{mlockall(MCL_CURRENT | MCL_FUTURE)}. See
-  mlockall(2) for more details. This function requires the C{ctypes} module.
+  This is equivalent to the C call mlockall(MCL_CURRENT|MCL_FUTURE),
+  see mlock(2) for more details. This function requires ctypes module.
 
-  @raises errors.NoCtypesError: If the C{ctypes} module is not found
+  @raises errors.NoCtypesError: if ctypes module is not found
 
   """
   if _ctypes is None:
     raise errors.NoCtypesError()
 
-  funcs = _FuncWrapper(_ctypes)
-
-  if funcs.mlockall_fn is None:
-    logging.debug("libc doesn't support mlockall(2)")
-  else:
-    if funcs.mlockall_fn(_MCL_CURRENT | _MCL_FUTURE) == 0:
-      logging.debug("Memory lock set")
-      return True
-
-    logging.error("Cannot set memory lock: %s", os.strerror(funcs.errno_fn()))
-
-  return False
+  try:
+    libc = _ctypes.cdll.LoadLibrary("libc.so.6")
+  except EnvironmentError, err:
+    logging.error("Failure trying to load libc: %s", err)
+    libc = None
+  if libc is None:
+    logging.error("Cannot set memory lock, ctypes cannot load libc")
+    return
+
+  # Some older version of the ctypes module don't have built-in functionality
+  # to access the errno global variable, where function error codes are stored.
+  # By declaring this variable as a pointer to an integer we can then access
+  # its value correctly, should the mlockall call fail, in order to see what
+  # the actual error code was.
+  # pylint: disable=W0212
+  libc.__errno_location.restype = _ctypes.POINTER(_ctypes.c_int)
+
+  if libc.mlockall(_MCL_CURRENT | _MCL_FUTURE):
+    # pylint: disable=W0212
+    logging.error("Cannot set memory lock: %s",
+                  os.strerror(libc.__errno_location().contents.value))
+    return
+
+  logging.debug("Memory lock set")
diff --git a/test/ganeti.utils.cfunc.mlockall_unittest.py b/test/ganeti.utils.cfunc_unittest.py
similarity index 97%
rename from test/ganeti.utils.cfunc.mlockall_unittest.py
rename to test/ganeti.utils.cfunc_unittest.py
index bafa71c8d..8c5c7469b 100755
--- a/test/ganeti.utils.cfunc.mlockall_unittest.py
+++ b/test/ganeti.utils.cfunc_unittest.py
@@ -41,15 +41,17 @@ class TestMlockallWithCtypes(unittest.TestCase):
   """Whether Mlockall() works if ctypes is present.
 
   """
+
   def test(self):
     if utils.ctypes:
-      self.assertTrue(utils.Mlockall())
+      utils.Mlockall()
 
 
 class TestMlockallWithNoCtypes(unittest.TestCase):
   """Whether Mlockall() raises an error if ctypes is not present.
 
   """
+
   def test(self):
     self.assertRaises(errors.NoCtypesError, utils.Mlockall, _ctypes=None)
 
-- 
GitLab