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