diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ebefd1d..0713a02 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -54,6 +54,9 @@ jobs: with: version: ${{ matrix.qt_version }} + - name: Setup MSVC environment for QMake + uses: ilammy/msvc-dev-cmd@v1 + - name: Build library with CMake run: | cmake . ${{ matrix.additional_arguments }} @@ -83,9 +86,6 @@ jobs: cmake . ${{ matrix.additional_arguments }} cmake --build . - - name: Setup MSVC environment for QMake - uses: ilammy/msvc-dev-cmd@v1 - - name: Build basic example with QMake working-directory: examples/basic/ run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f8b70a..1044c4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 3.5.1 + +* Bug Fix: Maximum QNativeIpcKey key size on macOS. - _Jonas Kvinge_ + +## 3.5.0 + +* Switch to the new QNativeIpcKey based QSharedMemory constructor with Qt 6.6 and higher. - _Jonas Kvinge_ + +## 3.4.1 + +* Improved Windows advapi32 link library dependency. - _Frederik Seiffert_ + ## 3.4.0 * Provide API for blocking sendMessage. - _Christoph Cullmann_ diff --git a/README.md b/README.md index 242aa1f..7971b5e 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Keeps the Primary Instance of your Application and kills each subsequent instances. It can (if enabled) spawn secondary (non-related to the primary) instances and can send data to the primary instance from secondary instances. -## Documentation +# [Documentation](https://itay-grudev.github.io/SingleApplication/) -You can find the full usage reference [here](https://itay-grudev.github.io/SingleApplication/classSingleApplication.html). +You can find the full usage reference and examples [here](https://itay-grudev.github.io/SingleApplication/classSingleApplication.html). ## Usage @@ -60,6 +60,50 @@ add_subdirectory(src/third-party/singleapplication) target_link_libraries(${PROJECT_NAME} SingleApplication::SingleApplication) ``` +Directly including this repository as a Git submodule, or even just a shallow copy of the +source code into new projects might not be ideal when using CMake. +Another option is using CMake's `FetchContent` module, available since version `3.11`. +```cmake + +# Define the minumun CMake version, as an example 3.24 +cmake_minimum_required(VERSION 3.24) + +# Include the module +include(FetchContent) + +# If using Qt6, override DEFAULT_MAJOR_VERSION +set(QT_DEFAULT_MAJOR_VERSION 6 CACHE STRING "Qt version to use, defaults to 6") + +# Set QAPPLICATION_CLASS +set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication") + + +# Declare how is the source going to be obtained +FetchContent_Declare( + SingleApplication + GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication + GIT_TAG master + #GIT_TAG e22a6bc235281152b0041ce39d4827b961b66ea6 +) + +# Fetch the repository and make it available to the build +FetchContent_MakeAvailable(SingleApplication) + +# Then simply use find_package as usual +find_package(SingleApplication) + +# Finally add it to the target_link_libraries() section +target_link_libraries(ClientePOS PRIVATE + Qt${QT_VERSION_MAJOR}::Widgets + Qt${QT_VERSION_MAJOR}::Network + Qt${QT_VERSION_MAJOR}::Sql + + SingleApplication::SingleApplication +) + +``` + + The library sets up a `QLocalServer` and a `QSharedMemory` block. The first instance of your Application is your Primary Instance. It would check if the shared memory block exists and if not it will start a `QLocalServer` and listen diff --git a/singleapplication.cpp b/singleapplication.cpp index 94fbac6..941a4a6 100644 --- a/singleapplication.cpp +++ b/singleapplication.cpp @@ -60,10 +60,34 @@ SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSeconda // block and QLocalServer d->genBlockServerName(); +//<<<<<<< v4.0 while( time.elapsed() < timeout ){ if( d->connectToPrimary( (timeout - time.elapsed()) * 2 / 3 )){ if( ! allowSecondary ) // If we are operating in single instance mode - terminate the program ::exit( EXIT_SUCCESS ); +/*======= + // To mitigate QSharedMemory issues with large amount of processes + // attempting to attach at the same time + SingleApplicationPrivate::randomSleep(); + +#ifdef Q_OS_UNIX + // By explicitly attaching it and then deleting it we make sure that the + // memory is deleted even after the process has crashed on Unix. +#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) + d->memory = new QSharedMemory( QNativeIpcKey( d->blockServerName ) ); +#else + d->memory = new QSharedMemory( d->blockServerName ); +#endif + d->memory->attach(); + delete d->memory; +#endif + // Guarantee thread safe behaviour with a shared memory block. +#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) + d->memory = new QSharedMemory( QNativeIpcKey( d->blockServerName ) ); +#else + d->memory = new QSharedMemory( d->blockServerName ); +#endif +>>>>>> master */ d->notifySecondaryStart( timeout ); return; diff --git a/singleapplication_p.cpp b/singleapplication_p.cpp index 085da38..62a9eb0 100644 --- a/singleapplication_p.cpp +++ b/singleapplication_p.cpp @@ -113,7 +113,12 @@ QString SingleApplicationPrivate::getUsername() void SingleApplicationPrivate::genBlockServerName() { +#ifdef Q_OS_MACOS + // Maximum key size on macOS is PSHMNAMLEN (31). + QCryptographicHash appData( QCryptographicHash::Md5 ); +#else QCryptographicHash appData( QCryptographicHash::Sha256 ); +#endif #if QT_VERSION < QT_VERSION_CHECK(6, 3, 0) appData.addData( "SingleApplication", 17 ); #else