Skip to content

bpo-46398: posixshmem module shm_rename freebsd support. #30621

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Doc/library/multiprocessing.shared_memory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,15 @@ copying of data.
This method has no effect on Windows, where the only way to delete a
shared memory block is to close all handles.

.. method:: rename(newname, flags)

Renames the underlying shared memory block to ``newname``. By
default, if ``newname`` already exists, it will be unlinked
beforehand. Passing the ``os.SHM_RENAME_EXCHANGE`` as ``flags``,
an exchange with ``newname`` will be proceeded instead. Passing
the ``os.SHM_RENAME_NOREPLACE`` as ``flags``, an error
will be triggered if ``newname`` already exists.

.. attribute:: buf

A memoryview of contents of the shared memory block.
Expand Down
22 changes: 22 additions & 0 deletions Lib/multiprocessing/shared_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from functools import partial
import mmap
import os
import platform
import errno
import struct
import secrets
Expand Down Expand Up @@ -253,6 +254,27 @@ def unlink(self):
if self._track:
resource_tracker.unregister(self._name, "shared_memory")

def rename(self, newname, flags = 0):
"""Renames a shared memory block.

The policy how the operation is handled depends on the flag passed.
The default behavior is if the newname already exists, it will
be unlinked beforehand.
With the SHM_RENAME_EXCHANGE flag, the old and new name will
be exchanged.
With the SHM_RENAME_NOREPLACE flag, an error will be returned
if the new name exists.
"""
if !platform.hasattr("shm_rename"):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if !platform.hasattr("shm_rename"):
if not platform.hasattr("shm_rename"):

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this platform.hasattr() function? Where does it come from?

raise OSError("Unsupported operation on this platform")

if newname:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it simply returns False if newname is empty and returns True otherwise? Why add such check in this method?

newname = "/" + newname if self._prepend_leading_slash else newname
self._fd = _posixshmem.shm_rename(self._name, newname, flags)
self._name = newname
return True
return False


_encoding = "utf8"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add :method:`rename` to the `multiprocessing.shared_memory` library for FreeBSD.
56 changes: 52 additions & 4 deletions Modules/_multiprocessing/clinic/posixshmem.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions Modules/_multiprocessing/posixshmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,53 @@ _posixshmem_shm_open_impl(PyObject *module, PyObject *path, int flags,
}
#endif /* HAVE_SHM_OPEN */

#ifdef HAVE_SHM_RENAME
/*[clinic input]
_posixshmem.shm_rename
path_from: unicode
path_to: unicode
flags: int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
flags: int
flags: int
/

I think it was mistake to make parameters keyword-or-positional in other functions. It is better to make them positional-only, it will help if we decide to rename parameters.

/

Rename a shared memory object.

Remove a shared memory object and relink to another path.
By default, if the destination path already exist, it will be unlinked.
With the SHM_RENAME_EXCHANGE flag, source and destination paths
will be exchanged.
With the SHM_RENAME_NOREPLACE flag, an error will be triggered
if the destination alredady exists.

[clinic start generated code]*/

static int
_posixshmem_shm_rename_impl(PyObject *module, PyObject *path_from,
PyObject *path_to, int flags)
/*[clinic end generated code: output=a9101f606826ad30 input=0373bfc9c491e123]*/
{
int rv;
int async_err = 0;
const char *from = PyUnicode_AsUTF8AndSize(path_from, NULL);
const char *to = PyUnicode_AsUTF8AndSize(path_to, NULL);
if (from == NULL || to == NULL) {
return -1;
}
do {
Py_BEGIN_ALLOW_THREADS
rv = shm_rename(from, to, flags);
Py_END_ALLOW_THREADS
} while (rv < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));

if (rv < 0) {
if (!async_err)
PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, path_from, path_to);
return -1;
}

return rv;
}
#endif /* HAVE_SHM_RENAME */

#ifdef HAVE_SHM_UNLINK
/*[clinic input]
_posixshmem.shm_unlink
Expand Down Expand Up @@ -111,6 +158,9 @@ _posixshmem_shm_unlink_impl(PyObject *module, PyObject *path)

static PyMethodDef module_methods[ ] = {
_POSIXSHMEM_SHM_OPEN_METHODDEF
#if defined(HAVE_SHM_RENAME)
_POSIXSHMEM_SHM_RENAME_METHODDEF
#endif
_POSIXSHMEM_SHM_UNLINK_METHODDEF
{NULL} /* Sentinel */
};
Expand Down
9 changes: 9 additions & 0 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -17288,6 +17288,15 @@ all_ins(PyObject *m)
#endif
#endif /* HAVE_MEMFD_CREATE */

#ifdef HAVE_SHM_RENAME
#ifdef SHM_RENAME_EXCHANGE
if (PyModule_AddIntMacro(m, SHM_RENAME_EXCHANGE)) return -1;
#endif
#ifdef SHM_RENAME_NOREPLACE
if (PyModule_AddIntMacro(m, SHM_RENAME_NOREPLACE)) return -1;
#endif
#endif /* HAVE_SHM_RENAME */

#if defined(HAVE_EVENTFD) && defined(EFD_CLOEXEC)
if (PyModule_AddIntMacro(m, EFD_CLOEXEC)) return -1;
#ifdef EFD_NONBLOCK
Expand Down
3 changes: 1 addition & 2 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -6873,7 +6873,7 @@ WITH_SAVE_ENV([
# endif
#endif
"
AC_CHECK_FUNCS([shm_open shm_unlink], [have_posix_shmem=yes], [have_posix_shmem=no])
AC_CHECK_FUNCS([shm_open shm_rename shm_unlink], [have_posix_shmem=yes], [have_posix_shmem=no])
_RESTORE_VAR([ac_includes_default])
])

Expand Down
3 changes: 3 additions & 0 deletions pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,9 @@
/* Define to 1 if you have the `shm_open' function. */
#undef HAVE_SHM_OPEN

/* Define to 1 if you have the `shm_rename' function. */
#undef HAVE_SHM_RENAME

/* Define to 1 if you have the `shm_unlink' function. */
#undef HAVE_SHM_UNLINK

Expand Down