summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-09-22 14:38:22 -0700
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2022-10-11 18:36:11 +0200
commit909112fa522a188373741797402445d22e3974b8 (patch)
tree0591cec8a062178271776c47cfe536d3f36129a9 /src/corelib/kernel
parent47ab723d82e9718027ac906aac75116590009053 (diff)
QSharedMemory/doc: update docs to be more modern
- We don't support HPUX any more, so no need to talk about it - Clarify that it's the QSharedMemory destructor that releases the resources on Unix systems - Explain the System V and POSIX backends and how to detect them - Add a note about Android not being supported. - Add a section about using QFile for shared memory Change-Id: I413ea647c2a5453b8307fffd17174c8083416529 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp112
1 files changed, 95 insertions, 17 deletions
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
index 79a5bfe1cb..2449564151 100644
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -105,22 +105,34 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
\li Unix: QSharedMemory "owns" the shared memory segment. When the
last thread or process that has an instance of QSharedMemory
attached to a particular shared memory segment detaches from the
- segment by destroying its instance of QSharedMemory, the Unix kernel
- release the shared memory segment. But if that last thread or
+ segment by destroying its instance of QSharedMemory, the destructor
+ releases the shared memory segment. But if that last thread or
process crashes without running the QSharedMemory destructor, the
shared memory segment survives the crash.
- \li HP-UX: Only one attach to a shared memory segment is allowed per
- process. This means that QSharedMemory should not be used across
- multiple threads in the same process in HP-UX.
+ \li Unix: QSharedMemory can be implemented by one of two different
+ backends, selected at Qt build time: System V or POSIX. Qt defaults to
+ using the System V API if it is available, and POSIX if not. These two
+ backends do not interoperate, so two applications must ensure they use the
+ same one, even if the native key (see setNativeKey()) is the same.
- \li Apple platforms: Sandboxed applications (including apps
- shipped through the Apple App Store) require the use of POSIX
- shared memory (instead of System V shared memory), which adds
- a number of limitations, including:
+ The POSIX backend can be explicitly selected using the
+ \c{-feature-ipc_posix} option to the Qt configure script. If it is enabled,
+ the \c{QT_POSIX_IPC} macro will be defined.
- \list
+ \li Sandboxed applications on Apple platforms (including apps
+ shipped through the Apple App Store): This environment requires
+ the use of POSIX shared memory (instead of System V shared memory).
+
+ Qt for iOS is built with support for POSIX shared memory out of the box.
+ However, Qt for \macos builds (including those from the Qt installer) default
+ to System V, making them unsuitable for App Store submission if QSharedMemory
+ is needed. See above for instructions to explicitly select the POSIX backend
+ when building Qt.
+
+ In addition, in a sandboxed environment, the following caveats apply:
+ \list
\li The key must be in the form \c {<application group identifier>/<custom identifier>},
as documented \l {https://developer.apple.com/library/archive/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW24}
{here} and \l {https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_application-groups}
@@ -143,11 +155,7 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
\endlist
- Qt for iOS comes with support for POSIX shared memory out of the box.
- With Qt for \macos an additional configure flag must be added when
- building Qt to enable the feature. To enable the feature pass
- \c {-feature-ipc_posix} Note that the pre-built Qt libraries for
- \macos available through the Qt installer do not include this feature.
+ \li Android: QSharedMemory is not supported.
\endlist
@@ -162,9 +170,79 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
\warning QSharedMemory changes the key in a Qt-specific way, unless otherwise
specified. Interoperation with non-Qt applications is achieved by first creating
a default shared memory with QSharedMemory() and then setting a native key with
- setNativeKey(). When using native keys, shared memory is not protected against
- multiple accesses on it (for example, unable to lock()) and a user-defined mechanism
+ setNativeKey(), after ensuring they use the same low-level API (System V or
+ POSIX). When using native keys, shared memory is not protected against multiple
+ accesses on it (for example, unable to lock()) and a user-defined mechanism
should be used to achieve such protection.
+
+ \section2 Alternative: Memory-Mapped File
+
+ Another way to share memory between processes is by opening the same file
+ using \l QFile and mapping it into memory using QFile::map() (without
+ specifying the QFileDevice::MapPrivateOption option). Any writes to the
+ mapped segment will be observed by all other processes that have mapped the
+ same file. This solution has the major advantages of being independent of the
+ backend API and of being simpler to interoperate with from non-Qt
+ applications. And since \l{QTemporaryFile} is a \l{QFile}, applications can
+ use that class to achieve clean-up semantics and to create unique shared
+ memory segments too.
+
+ To achieve locking of the shared memory segment, applications will need to
+ deploy their own mechanisms. This can be achieved by using \l
+ QBasicAtomicInteger or \c{std::atomic} in a pre-determined offset in the
+ segment itself. Higher-level locking primitives may be available on some
+ operating systems; for example, on Linux, \c{pthread_mutex_create()} can be
+ passed a flag to indicate that the mutex resides in a shared memory segment.
+
+ A major drawback of using file-backed shared memory is that the operating
+ system will attempt to write the data to permanent storage, possibly causing
+ noticeable performance penalties. To avoid this, applications should locate a
+ RAM-backed filesystem, such as \c{tmpfs} on Linux (see
+ QStorageInfo::fileSystemType()), or pass a flag to the native file-opening
+ function to inform the OS to avoid committing the contents to storage.
+
+ File-backed shared memory must be used with care if another process
+ participating is untrusted. The files may be truncated/shrunk and cause
+ applications accessing memory beyond the file's size to crash.
+
+ \section3 Linux hints on memory-mapped files
+
+ On modern Linux systems, while the \c{/tmp} directory is often a \c{tmpfs}
+ mount point, that is not a requirement. However, the \c{/dev/shm} directory
+ is required to be a \c{tmpfs} and exists for this very purpose. Do note that
+ it is world-readable and writable (like \c{/tmp} and \c{/var/tmp}), so one
+ must be careful of the contents revealed there. Another alternative is to use
+ the XDG Runtime Directory (see QStandardPaths::writableLocation() and
+ \l{QStandardPaths::RuntimeLocation}), which on Linux systems using systemd is
+ a user-specific \c{tmpfs}.
+
+ An even more secure solution is to create a "memfd" using \c{memfd_create(2)}
+ and use interprocess communication to pass the file descriptor, like
+ \l{QDBusUnixFileDescriptor} or by letting the child process of a \l{QProcess}
+ inherit it. "memfds" can also be sealed against being shrunk, so they are
+ safe to be used when communicating with processes with a different privilege
+ level.
+
+ \section3 FreeBSD hints on memory-mapped files
+
+ FreeBSD also has \c{memfd_create(2)} and can pass file descriptors to other
+ processes using the same techniques as Linux. It does not have temporary
+ filesystems mounted by default.
+
+ \section3 Windows hints on memory-mapped files
+
+ On Windows, the application can request the operating system avoid committing
+ the file's contents to permanent storage. This request is performed by
+ passing the \c{FILE_ATTRIBUTE_TEMPORARY} flag in the \c{dwFlagsAndAttributes}
+ \c{CreateFile} Win32 function, the \c{_O_SHORT_LIVED} flag to \c{_open()}
+ low-level function, or by including the modifier "T" to the \c{fopen()} C
+ runtime function.
+
+ There's also a flag to inform the operating system to delete the file when
+ the last handle to it is closed (\c{FILE_FLAG_DELETE_ON_CLOSE},
+ \c{_O_TEMPORARY}, and the "D" modifier), but do note that all processes
+ attempting to open the file must agree on using this flag or not using it. A
+ mismatch will likely cause a sharing violation and failure to open the file.
*/
/*!