Skip to content
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

Using QSharedMemory for SingleApplication might stop working as of Qt 6.6 #170

Closed
jonaski opened this issue May 4, 2023 · 8 comments
Closed

Comments

@jonaski
Copy link
Collaborator

jonaski commented May 4, 2023

According to Thiago Macieira we are using QSharedMemory for something it wasn't designed for. Basically we are using it in the same way as Qt Creator's QtSingleApplication, which he claims is wrong. Might be worth considering switching to using a lockfile instead.

The QString based constructor we use will be deprecated as of 6.10, with the recent changes to QSharedMemory, it currently does not work at all in our use-case.
When using the new QNativeIpcKey constructor, it works, but it's impossible to release the previous QSharedMemory instance when the program crashes or is forcefully quit. See: https://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/ipc/qsharedmemory.h

The bug report I filed is here: https://bugreports.qt.io/browse/QTBUG-111855

I switched to https://github.com/KDAB/KDSingleApplication which uses a lockfile, at least until we can solve this, because I use Qt from dev for debugging, and I switched to the new QNativeIpcKey constructor because the old didn't work at all, and will be deprecated anyway, but each time I had to stop and start debugging I had to rename the appdata name or remove the SingleApplication code which was too much hassle.

@itay-grudev
Copy link
Owner

Technically I found a workaround for releasing QSharedMemory after a process has crashed. On Windows it's not a problem, but on Linux by initializing it, then deleting forces the kernel to clean up the shared memory. This way the moment e initialize it again it's the first time it's initialized. Take a look at the code below.

#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.
d->memory = new QSharedMemory( d->blockServerName );
d->memory->attach();
delete d->memory;
#endif
// Guarantee thread safe behaviour with a shared memory block.
d->memory = new QSharedMemory( d->blockServerName );

Lockfiles on the other hand suffer from the same problem when an instance has crashed. Originally I tried implementing it with a lockfile, but found that to be too unreliable. But maybe we can give it another look.

Another option would be to handle the SingleAplication functionality completely through QLocalSocket. If there is a primary instance to connect to - use it. Otherwise create one. I think we can use the fact that you can't bind two programs to the same address for single instance protection.

@itay-grudev
Copy link
Owner

One issue when using local sockets that I know of is if an app is busy and doesn't reply to the message in time. It can happen if the main event loop is blocked doing a task. To account for this we'll have to always start a separate thread for the SingleApplication QLocalServer.

@itay-grudev itay-grudev mentioned this issue Jun 12, 2023
@emericg
Copy link
Contributor

emericg commented Sep 23, 2023

I can confirm, it looks like SingleApplication doesn't work anymore with Qt 6.6...

@jonaski
Copy link
Collaborator Author

jonaski commented Sep 28, 2023

@emericg Try #177

@emericg
Copy link
Contributor

emericg commented Sep 28, 2023

Works great on Linux, thanks, I'll try on other platforms tomorrow!

@itay-grudev
Copy link
Owner

Fixed in #177 and released in v3.5.0.

@itay-grudev
Copy link
Owner

Thanks @jonaski

@jonaski
Copy link
Collaborator Author

jonaski commented Nov 18, 2023

Thiago just posted on the Qt dev mailing-list, see https://lists.qt-project.org/pipermail/development/2023-November/044680.html and https://codereview.qt-project.org/c/qt/qtbase/+/518039
Shortly summarized:
QSharedMemory is flawed by design and unless someone else steps up to fix QSharedMemory, it will be deprecated in Qt 6 and removed in Qt 7.
I would like to dig into this myself, but I'm already working 4-7 hours every day on open source work in addition to a full time job (which is non-Qt), and I'm already way behind on other stuff so I can't find the time now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants