• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 posixshmem - A Python extension that provides shm_open() and shm_unlink()
3 */
4 
5 // Need limited C API version 3.13 for Py_mod_gil
6 #include "pyconfig.h"   // Py_GIL_DISABLED
7 #ifndef Py_GIL_DISABLED
8 #  define Py_LIMITED_API 0x030d0000
9 #endif
10 
11 #include <Python.h>
12 
13 #include <string.h>               // strlen()
14 #include <errno.h>                // EINTR
15 #ifdef HAVE_SYS_MMAN_H
16 #  include <sys/mman.h>           // shm_open(), shm_unlink()
17 #endif
18 
19 
20 /*[clinic input]
21 module _posixshmem
22 [clinic start generated code]*/
23 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=a416734e49164bf8]*/
24 
25 /*
26  *
27  * Module-level functions & meta stuff
28  *
29  */
30 
31 #ifdef HAVE_SHM_OPEN
32 /*[clinic input]
33 _posixshmem.shm_open -> int
34     path: unicode
35     flags: int
36     mode: int = 0o777
37 
38 # "shm_open(path, flags, mode=0o777)\n\n\
39 
40 Open a shared memory object.  Returns a file descriptor (integer).
41 
42 [clinic start generated code]*/
43 
44 static int
_posixshmem_shm_open_impl(PyObject * module,PyObject * path,int flags,int mode)45 _posixshmem_shm_open_impl(PyObject *module, PyObject *path, int flags,
46                           int mode)
47 /*[clinic end generated code: output=8d110171a4fa20df input=e83b58fa802fac25]*/
48 {
49     int fd;
50     int async_err = 0;
51     Py_ssize_t name_size;
52     const char *name = PyUnicode_AsUTF8AndSize(path, &name_size);
53     if (name == NULL) {
54         return -1;
55     }
56     if (strlen(name) != (size_t)name_size) {
57         PyErr_SetString(PyExc_ValueError, "embedded null character");
58         return -1;
59     }
60     do {
61         Py_BEGIN_ALLOW_THREADS
62         fd = shm_open(name, flags, mode);
63         Py_END_ALLOW_THREADS
64     } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
65 
66     if (fd < 0) {
67         if (!async_err)
68             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
69         return -1;
70     }
71 
72     return fd;
73 }
74 #endif /* HAVE_SHM_OPEN */
75 
76 #ifdef HAVE_SHM_UNLINK
77 /*[clinic input]
78 _posixshmem.shm_unlink
79     path: unicode
80 
81 Remove a shared memory object (similar to unlink()).
82 
83 Remove a shared memory object name, and, once all processes  have  unmapped
84 the object, de-allocates and destroys the contents of the associated memory
85 region.
86 
87 [clinic start generated code]*/
88 
89 static PyObject *
_posixshmem_shm_unlink_impl(PyObject * module,PyObject * path)90 _posixshmem_shm_unlink_impl(PyObject *module, PyObject *path)
91 /*[clinic end generated code: output=42f8b23d134b9ff5 input=8dc0f87143e3b300]*/
92 {
93     int rv;
94     int async_err = 0;
95     Py_ssize_t name_size;
96     const char *name = PyUnicode_AsUTF8AndSize(path, &name_size);
97     if (name == NULL) {
98         return NULL;
99     }
100     if (strlen(name) != (size_t)name_size) {
101         PyErr_SetString(PyExc_ValueError, "embedded null character");
102         return NULL;
103     }
104     do {
105         Py_BEGIN_ALLOW_THREADS
106         rv = shm_unlink(name);
107         Py_END_ALLOW_THREADS
108     } while (rv < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
109 
110     if (rv < 0) {
111         if (!async_err)
112             PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path);
113         return NULL;
114     }
115 
116     Py_RETURN_NONE;
117 }
118 #endif /* HAVE_SHM_UNLINK */
119 
120 #include "clinic/posixshmem.c.h"
121 
122 static PyMethodDef module_methods[ ] = {
123     _POSIXSHMEM_SHM_OPEN_METHODDEF
124     _POSIXSHMEM_SHM_UNLINK_METHODDEF
125     {NULL} /* Sentinel */
126 };
127 
128 
129 static PyModuleDef_Slot module_slots[] = {
130     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
131     {Py_mod_gil, Py_MOD_GIL_NOT_USED},
132     {0, NULL}
133 };
134 
135 
136 static struct PyModuleDef _posixshmemmodule = {
137     PyModuleDef_HEAD_INIT,
138     .m_name = "_posixshmem",
139     .m_doc = "POSIX shared memory module",
140     .m_size = 0,
141     .m_methods = module_methods,
142     .m_slots = module_slots,
143 };
144 
145 /* Module init function */
146 PyMODINIT_FUNC
PyInit__posixshmem(void)147 PyInit__posixshmem(void)
148 {
149     return PyModuleDef_Init(&_posixshmemmodule);
150 }
151