3

My Environment

More Background Info to Understand My Question

As for my understanding, Modules/_multiprocessing/semaphore.c implements the internal Python object SemLock that is used to implement the multiprocessing.synchronize.SemLock in the Python standard library:

class SemLock(object):
    def __init__(self, kind, value, maxvalue, *, ctx):
        (...A lot of other code...)
                sl = self._semlock = _multiprocessing.SemLock(  # <-- Here.

Modules/_multiprocessing/semaphore.c implements this internal SemLock object by defining a SemLockObject in C and exporting it as SemLock in Python.

Here is the C definition:

typedef struct {
    PyObject_HEAD
    SEM_HANDLE handle;
    unsigned long last_tid;
    int count;
    int maxvalue;
    int kind;
    char *name;  /* <--- It has 'name'. */
} SemLockObject;

Later SemLockObject is exported as SemLock, in Line #617:

PyTypeObject _PyMp_SemLockType = {
    PyVarObject_HEAD_INIT(NULL, 0)
    /* tp_name           */ "_multiprocessing.SemLock",
    /* tp_basicsize      */ sizeof(SemLockObject),

Along with SemLock, several _semlock_members_ are exported, too, including 'name'. See Line #608:

static PyMemberDef semlock_members[] = {
    {"handle", T_SEM_HANDLE, offsetof(SemLockObject, handle), READONLY,
     ""},
    {"kind", T_INT, offsetof(SemLockObject, kind), READONLY,
     ""},
    {"maxvalue", T_INT, offsetof(SemLockObject, maxvalue), READONLY,
     ""},
    {"name", T_STRING, offsetof(SemLockObject, name), READONLY,
     ""},  /* <--- Here it is. */
    {NULL}
};

Therefore, there is a reason to believe that I can access the name member at run time. However, when I inspect the members of this internal SemLock object, I don't see the name member. Here is my inspection code:

import multiprocessing as mp
import inspect

lock = mp.Semaphore(1)
members = inspect.getmembers(lock._semlock)
for (name, _) in members:
    print name

Here is the result:

SEM_VALUE_MAX
__class__
__delattr__
__doc__
__enter__
__exit__
__format__
__getattribute__
__hash__
__init__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__sizeof__
__str__
__subclasshook__
_after_fork
_count
_get_value
_is_mine
_is_zero
_rebuild 
acquire 
handle      <-- 'handle' is defined in 'semlock_members'
kind        <-- 'kind' is defined in 'semlock_members'
maxvalue    <-- 'maxvalue' is defined in 'semlock_members'
release

But where is name??

In fact, if we look at multiprocessing.synchronize.SemLock.__init__ Line #76, it tests the value of _semlock.name:

if self._semlock.name is not None:

which makes me think the underlying _semlock has the 'name' member because otherwise the code would raise an exception like "AttributeError: '_multiprocessing.SemLock' object has no attribute 'name'".

I must have missed something somewhere. Would someone help me point it out??

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
yaobin
  • 2,436
  • 5
  • 33
  • 54

1 Answers1

4

You're using Python 2.7, but looking at Python 3.7 source. See 2.7's semlock_members.

Zachary Ware
  • 325
  • 2
  • 8
  • @yaobin, if it's not clear -- the `master`/`default` development branch long ago transitioned to support the Python 3 language. So, if you checkout source from Github, e.g., you must go back to 2.7 to see what it looked like then. – Brian Cain May 18 '17 at 19:18
  • @BrianCain Thanks for pointing out! In fact, this morning I woke up and all of a sudden it hit me: Maybe I was looking at the wrong version?? Kind of embarrassing to spend so long time posting a question and bothering so many people but which can be solved by one simple check... – yaobin May 19 '17 at 13:00