summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--setup.py95
-rw-r--r--shm/shmmodule.c60
2 files changed, 129 insertions, 26 deletions
diff --git a/setup.py b/setup.py
index 63451e8..2a3cd90 100644
--- a/setup.py
+++ b/setup.py
@@ -16,13 +16,106 @@ from distutils.core import setup, Extension
from portato.constants import FRONTENDS, VERSION, DATA_DIR, ICON_DIR, PLUGIN_DIR, TEMPLATE_DIR
### copied from shm's setup.py ###
+
+import popen2
+import tempfile
+
+# shm makes use of the ipc_perm structure defined in include/sys/ipc.h (or include/bits/ipc.h
+# on some systems). That structure includes an element called key, _key or __key depending
+# on the OS. Here's the variations I've been able to find with OS version numbers where
+# possible.
+# key: FreeBSD 6, AIX, Solaris, OS X 10.3, OS X 10.4 (conditionally)
+# _key: NetBSD, OS X 10.4 (conditionally)
+# __key: Debian 4 (Etch), Ubuntu 7, RH 3.3 & 3.4
+
+# OS X side note: OS X 10.4's ipc.h (see /Developer/SDKs/MacOSX10.4u.sdk/usr/include/sys/ipc.h)
+# defines structs called __ipc_perm_old (which uses key) and __ipc_perm_new (which uses _key).
+# Use of __ipc_perm_new is inside this:
+# #if defined(__POSIX_C_SOURCE) || defined(kernel) || defined(__LP64__)
+# Obviously __ipc_perm_new is the preferred version. This code doesn't use that yet but
+# will probably do so in some future version when compiled on OS X >= 10.4.
+
+# Trying to enumerate all of the variations is a fool's errand so instead I figure it out
+# on the fly using the function CountKeyUnderscores() below.
+
+# Lots of systems use the unadorned "key" so that's the default when I'm forced to guess.
+COUNT_KEY_UNDERSCORES_DEFAULT = 0
+
+def CountKeyUnderscores():
+ """ Uses trial-and-error with the system's C compiler to figure out the number of
+ underscores preceding key in the ipc_perm structure. Returns 0, 1 or 2. In case of
+ error, it makes a guess and hopes for the best.
+ """
+ UnderscoresCount = COUNT_KEY_UNDERSCORES_DEFAULT
+
+ underscores = { }
+
+ # mktemp isn't secure, but I don't care since I use it only for compiling this dummy code.
+ # Using mktemp() allows me to keep this code compatible with Python < 2.3.
+ path = tempfile.mktemp(dir='.')
+ os.mkdir(path)
+ if path[-1] != "/": path += '/'
+
+ # Here I compile three mini-programs with key, _key and __key. Theoretically,
+ # two should fail and one should succeed, and that will tell me how this platform names
+ # ipc_perm.key. If the number of successes != 1, something's gone wrong.
+ # I use popen2.Popen4() in order to trap (and discard) stderr so that the user doesn't
+ # see the compiler errors I'm deliberately generating here.
+ src = """
+#include <sys/ipc.h>
+int main(void) { struct ipc_perm foo; foo.%skey = 42; }
+
+"""
+ for i in range(0, 3):
+ # I'd prefer to feed the C source to the compiler via stdin so as to entirely avoid
+ # using files and directories, but I had trouble on Ubuntu getting echo to cooperate.
+ filename = "%d.c" % i
+ file(path + filename, "w").write(src % ('_' * i))
+
+ cmd = ["cc", "-c", "-o", "/dev/null", "%s" % path + filename]
+
+ po = popen2.Popen4(cmd)
+ if not po.wait(): underscores[i] = True
+
+ # Clean up
+ os.remove(path + filename)
+
+ os.rmdir(path)
+
+ KeyCount = len(underscores.keys())
+
+ if KeyCount == 1:
+ UnderscoresCount = underscores.keys()[0]
+ else:
+ print """
+*********************************************************************
+* I was unable to detect the structure of ipc_perm on your system. *
+* I'll make my best guess, but compiling might fail anyway. Please *
+* email this message, the error code of %d, and the name of your OS *
+* to the contact at http://NikitaTheSpider.com/python/shm/. *
+*********************************************************************
+""" % KeyCount
+
+ return UnderscoresCount
+
+
MacrosAndDefines = [ ]
# HAVE_UNION_SEMUN needs to be #defined on FreeBSD and OS X and must *not* be #defined
# on Linux. On other systems, I'm not sure. Please let me know if you find that you
# need to make changes for your platform.
-if ("bsd" in sys.platform) or ("darwin" in sys.platform):
+if (sys.platform.find("bsd") != -1) or (sys.platform.find("darwin") != -1):
MacrosAndDefines.append( ('HAVE_UNION_SEMUN', None) )
+
+KeyUnderscores = CountKeyUnderscores()
+
+if KeyUnderscores == 2:
+ MacrosAndDefines.append( ('TWO_UNDERSCORE_KEY', None) )
+elif KeyUnderscores == 1:
+ MacrosAndDefines.append( ('ONE_UNDERSCORE_KEY', None) )
+else:
+ MacrosAndDefines.append( ('ZERO_UNDERSCORE_KEY', None) )
+
### end copy ###
def plugin_list (*args):
diff --git a/shm/shmmodule.c b/shm/shmmodule.c
index cee6d7a..98596f1 100644
--- a/shm/shmmodule.c
+++ b/shm/shmmodule.c
@@ -1,6 +1,6 @@
/****************************************************************************
*
- * « shmmodule.c © 1997, 1998 by INRIA. All rights reserved.
+ * shmmodule.c Copyright 1997, 1998 by INRIA. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
@@ -22,25 +22,29 @@
* LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION, HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT,
* INCLUDING NEGLIGENCE OR OTHERWISE, ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. »
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
***************************************************************************/
-/* Python Shared Memory module by Vladimir Marangozov */
+/* Python Shared Memory module
+ Written by Vladimir Marangozov
+ Adopted by Philip Semanchuk
-/*
This module provides an interface to System V shared memory IPC.
Version history:
- - 1.0 - Released by Mr. Marangozov in the 1990s.
- - 1.1 - Released by me. Fixes a few bugs (including some memory leaks) and adds the ability
- to read the blocking flag on semaphores.
- - 1.1.1 - Updated setup.py to handle compile options for Linux users.
-
- See http://NikitaTheSpider.com/python/shm/ for more thorough documentation, updates, contact
- info, setup.py, a more Pythonic wrapper, etc.
+ - 1.0 (sometime in the 1990s) - Released by Mr. Marangozov
+ - 1.1 (Feb 2007) - Released by me, Philip Semanchuk. Fixes a few bugs (including some
+ memory leaks) and adds the ability to read the blocking flag on semaphores.
+ - 1.1.1 (Mar 2007)- Updated setup.py to handle compile options for Linux users.
+ - 1.1.2 (Nov 2007) - Fixed a sprintf() format in repr to handle size_t.
+ - 1.1.3 (Nov 2007) - Changed #define of key to _key instead of __key for OS X Leopard.
+ Thanks to Bill Hart.
+ - 1.1.4 (Jan 2008) - Changed the reference to key in the ipc_perm structure to the
+ explicit #define IPC_PERM_KEY_NAME.
- Philip Semanchuk, Feb. 2007
+ See http://NikitaTheSpider.com/python/shm/ for more thorough documentation, a more Pythonic
+ wrapper, updates, contact info, setup.py, etc.
Module interface:
@@ -122,18 +126,23 @@
#include "structmember.h"
/* v1.1 - added */
-//#ifdef __FreeBSD__
-//#include <machine/param.h> /* for system definition of PAGE_SIZE */
-//#endif
+#ifdef __FreeBSD__
+#include <machine/param.h> /* for system definition of PAGE_SIZE */
+#endif
#include <sys/types.h>
#include <sys/ipc.h> /* for system's IPC_xxx definitions */
#include <sys/shm.h> /* for shmget, shmat, shmdt, shmctl */
#include <sys/sem.h> /* for semget, semctl, semop */
-#if defined(__GLIBC__)
-#define key __key
-#endif /* __GLIBC__ */
+/* v1.1.4 - The name of this member varies and is sniffed out by setup.py. */
+#if defined(ZERO_UNDERSCORE_KEY)
+#define IPC_PERM_KEY_NAME key
+#elif defined(ONE_UNDERSCORE_KEY)
+#define IPC_PERM_KEY_NAME _key
+#elif defined(TWO_UNDERSCORE_KEY)
+#define IPC_PERM_KEY_NAME __key
+#endif
/*
-- Exception type for errors detected by this module.
@@ -221,7 +230,7 @@ check_memory_identity(PyShmObj *o)
int new_shmid;
int old_shmid = o->shmid;
int old_size = o->ds.shm_segsz;
- key_t old_key = o->ds.shm_perm.key;
+ key_t old_key = o->ds.shm_perm.IPC_PERM_KEY_NAME;
/*
-- 1. Try to get the segment identified by the old key (if not IPC_PRIVATE)
@@ -239,7 +248,7 @@ check_memory_identity(PyShmObj *o)
new_shmid = old_shmid;
if ((shmctl(new_shmid, IPC_STAT, &(o->ds)) != -1) &&
(old_size == o->ds.shm_segsz) &&
- (old_key == o->ds.shm_perm.key))
+ (old_key == o->ds.shm_perm.IPC_PERM_KEY_NAME))
return 1;
return 0;
}
@@ -485,7 +494,7 @@ static struct memberlist memory_memberlist[] = {
{"cgid", T_INT, OFF2(cgid), RO}, /* 0 (gid_t) */
{"cpid", T_INT, OFF1(shm_cpid), RO}, /* 1 (pid_t) */
{"cuid", T_INT, OFF2(cuid), RO}, /* 2 (uid_t) */
- {"key", T_INT, OFF2(key), RO}, /* 3 (key_t) */
+ {"key", T_INT, OFF2(IPC_PERM_KEY_NAME), RO}, /* 3 (key_t) */
{"lpid", T_INT, OFF1(shm_lpid), RO}, /* 4 (pid_t) */
{"shmid", T_INT, OFF(shmid), RO}, /* 5 (int) */
{"size", T_INT, OFF1(shm_segsz), RO}, /* 6 (int) */
@@ -559,8 +568,9 @@ PyShmMemory_repr(PyShmObj *self, char *name)
sprintf(buf2, "None");
else
/* v 1.1 - changed format from %lx to %p. */
+ /* v 1.1.2 - changed %u to %zu. */
sprintf(buf2, "0x%p", self->addr);
- sprintf(buf, "<%s shared memory object, id=%d, size=%u, addr=%s>",
+ sprintf(buf, "<%s shared memory object, id=%d, size=%zu, addr=%s>",
(self->addr == NULL) ? "detached" : (self->mode & SHM_RDONLY) ?
"attached RO" : "attached R/W",
self->shmid,
@@ -601,7 +611,7 @@ check_semaphore_identity(PyShmSemObj *o)
int new_semid;
int old_semid = o->semid;
unsigned short old_nsems = o->ds.sem_nsems;
- key_t old_key = o->ds.sem_perm.key;
+ key_t old_key = o->ds.sem_perm.IPC_PERM_KEY_NAME;
semctl_arg arg;
if (old_key != IPC_PRIVATE) {
@@ -614,7 +624,7 @@ check_semaphore_identity(PyShmSemObj *o)
arg.buf = &(o->ds);
if ((semctl(new_semid, 0, IPC_STAT, arg) != -1) &&
(old_nsems == o->ds.sem_nsems) &&
- (old_key == o->ds.sem_perm.key))
+ (old_key == o->ds.sem_perm.IPC_PERM_KEY_NAME))
return 1;
return 0;
}
@@ -875,7 +885,7 @@ static PyMethodDef semaphore_methods[] = {
static struct memberlist semaphore_memberlist[] = {
{"cgid", T_INT, OFF2(cgid), RO}, /* 0 (gid_t) */
{"cuid", T_INT, OFF2(cuid), RO}, /* 1 (uid_t) */
- {"key", T_INT, OFF2(key), RO}, /* 2 (key_t) */
+ {"key", T_INT, OFF2(IPC_PERM_KEY_NAME), RO}, /* 2 (key_t) */
{"semid", T_INT, OFF(semid), RO}, /* 3 (int) */
{"gid", T_INT, OFF2(gid), RO}, /* 4 (gid_t) */
{"uid", T_INT, OFF2(uid), RO}, /* 5 (uid_t) */