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

SingleApplication blocks application on macOS with Apple M1 #136

Closed
csuft opened this issue Aug 4, 2021 · 49 comments
Closed

SingleApplication blocks application on macOS with Apple M1 #136

csuft opened this issue Aug 4, 2021 · 49 comments

Comments

@csuft
Copy link

csuft commented Aug 4, 2021

Hi, it's nice to find this open source project and I added this project in our source code. It works like charm both on Windows and macOS, except for macOS with Apple M1. We received some feedbacks from our client that the application won't be launched after installation. The log looks like the following:

iShot2021-08-04 10 23 38

It seems the application is blocked because of lock in shared memory. I don't know if anybody encountered this issue before. There is a similar issue in list #58 but I am not sure how to resolve it.

@itay-grudev
Copy link
Owner

I believe I read something, somewhere about a similar issue on apps running on M1s. Something about shared memory... Let me try to find it.

@itay-grudev
Copy link
Owner

From what I can see, there shouldn't be an issue with shared memory on M1 MacOS. But without having access to M1 hardware it would be hard for me to reproduce it. Any ideas? Do you have access to M1 hardware?

@itay-grudev
Copy link
Owner

One way would be to add an exception, but I'd rather investigate the real cause of the issue. For all I know it may be a Qt bug in the underlying implementation.

  1. Can you try a more recent Qt version?
  2. Can you try building your app on M1 hardware?

#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
// On Android and iOS since the library is not supported fallback to
// standard QApplication behaviour by simply returning at this point.
qWarning() << "SingleApplication is not supported on Android and iOS systems.";
return;
#endif

@csuft
Copy link
Author

csuft commented Aug 5, 2021

Yeah, I compiled my project on M1 mac mini(Version 11.2), and the Qt version is 5.15.2. I don't have too much to compile other versions and currently we don't have any plans to migrate to Qt 6.

@itay-grudev
Copy link
Owner

I need assistance for this as I currently don't have access to an M1 machine and cannot look into it in dept. But my guess is there is some Qt issue on that platform.

@HealsCodes
Copy link

Hey, I'm happy to help if I can - I'm using SingleApplication for one of my projects and I'm working solely on an M1 MacBook Air.

For a starter I'm not observing the problem with using SingleApplication with allowSecondary=false under Qt6 arm64.
So if it was a Qt bug then it has been fixed.

However if I try to compile against an arm64 version of Qt5 I also can't reproduce the issue.
So it seems like the problem might be related to using the official x86_64 Qt5 build under Rosetta2 on an M1.

(note: @csuft that Qt5 isn't officially supported natively on M1 so your applications will have to rely on Rosetta2 x86_64 translation which will eventually be removed in the future).

@itay-grudev
Copy link
Owner

@csuft Is the problem still present in a build with the latest Qt5 version, to confirm that the issue is gone as @Shirk suggests?

@itay-grudev
Copy link
Owner

I am closing the issue for now. If there is new feedback on this - please feel free to share it and we could reopen it.

@danryu
Copy link

danryu commented Oct 27, 2022

I'm seeing this issue now, when trying to run a Universal (Intel+AppleSilicon) app built using Qt 6.3.2, running on an intel MacBook.

When I run the app from the terminal I simply see:

SingleApplication: Unable to create block.
SingleApplication:  1 "QSharedMemoryPrivate::initKey: unable to set key on lock"

Is the M1-2/arm support not likely to work? I was hoping to deploy singleapplication for our mac users ...
(app here: https://github.com/koord-live/koord-app )

@itay-grudev
Copy link
Owner

itay-grudev commented Oct 27, 2022 via email

@danryu
Copy link

danryu commented Oct 27, 2022

I also don't have access to an M1 machine.
I can help debug this use case (running a Universal build on intel mac) but I don't have project bandwidth or expertise to start modifying SingleApplication.

@danryu
Copy link

danryu commented Oct 27, 2022

Is it necessary to actually have a physical M1 mac, if I can reproduce the error by running the Universal build on intel?

Otherwise is this a Won't Fix scenario?
Which would be a bummer as M1 macs are only gonna get more popular, and I really wanted SingleApplication working everywhere...

@HealsCodes
Copy link

HealsCodes commented Oct 27, 2022

I - apparently - have access to an M1, what would be required to reproduce this?

(and to answer the question: M1 bugs are CPU-specific, the M1 macOS environment differs a lot from an intel* build and the intel slice of a universal binary is completely independent in it's behaviour)

@danryu
Copy link

danryu commented Oct 27, 2022

I - apparently - have access to an M1, what would be required to reproduce this?

The universal build that fails for me on Intel will probably also fail for you on M1:
https://github.com/koord-live/koord-app/releases/download/r4_0_16pre6/Koord_4.0.16_.dmg

If you install and run from Terminal, you will likely the same error I posted above.

(and to answer the question: M1 bugs are CPU-specific, the M1 macOS environment differs a lot from an intel* build and the intel slice of a universal binary is completely independent in it's behaviour)

I'm not sure this is an "M1 bug" or what one of those is exactly. I can say that the Universal build dmg installer is 39Mb in size, and the individual intel/M1 ones are 37Mb - only 2Mb smaller.
Also running the Universal build running on Intel seems to fail with the same error as OP on M1, so they can't be that independent.
(Btw this is a blocker for submitting to App Store as Universal build is required to fully support both CPU archs for users.)

@danryu
Copy link

danryu commented Oct 27, 2022

@Shirk
Maybe the simplest reproduction would be if you ran the simplest example in QtCreator:
https://github.com/itay-grudev/SingleApplication/tree/master/examples/basic

If that works/fails that would provide a good baseline for debugging :)

@HealsCodes
Copy link

I'm not sure this is an "M1 bug" or what one of those is exactly. I can say that the Universal build dmg installer is 39Mb in size, and the individual intel/M1 ones are 37Mb - only 2Mb smaller. Also running the Universal build running on Intel seems to fail with the same error as OP on M1, so they can't be that independent. (Btw this is a blocker for submitting to App Store as Universal build is required to fully support both CPU archs for users.)

You're looking at a DMG.. which is a compressed archive file and has zero indication of it's content sizes.
The Koord.app is over 200MB as universal binary and most of that is Qt.

If you remove the unused architecture part you can se that almost everything is different:

 /tmp % du -sh Koord.app
283M	Koord.app
 /tmp % du -sh Koord_thin_arm64.app
140M	Koord_thin_arm64.app
 /tmp % du -sh Koord_thin_intel.app
149M	Koord_thin_intel.app

The Problem is also not with QSingleApplication but rather with your codesigning entitlements which prevent shared memory usage, which in turn causes QSharedMemoryPrivate::initKey to fail.

You can test this by "dummy signing" your application without a sandbox:
codesign -s - -f --deep Koord.app/

Which produces a working application (because no sandboxing is enforced)
I'm still checking which entitlements key is required but it's fair to say that this is out-of-scope for QSingleApplication.

@HealsCodes
Copy link

Update - more research - still not QSingleApplication's fault; Qt has a number of "specialities" for Apple & the Mac AppStore:

  • you need to build Qt6 yourself and make sure to use the "-appstore-compliant" flag as per QTBUG-106910
  • Shared memory has to be created in the form "DEVTEAMID.app-group/shared"
    • QSingleApplication could do that, but it would have to know about the fact in the first place
  • your app might require an associated app group on Apples profiles & identifiers page (see Qt6 - QSharedMemory on Apple Platforms)

Screenshot 2022-10-27 at 18 23 13@2x

@itay-grudev
Copy link
Owner

itay-grudev commented Oct 27, 2022 via email

@itay-grudev
Copy link
Owner

itay-grudev commented Oct 27, 2022 via email

@danryu
Copy link

danryu commented Oct 27, 2022

Update - more research - still not QSingleApplication's fault; Qt has a number of "specialities" for Apple & the Mac AppStore:

I don't need to do any of that normally. The Koord app has been building and running fine for ages, and also accepted without problem into App store. None of the links you specified are necessary.
I certainly don't need to build Qt6 myself to create a working Mac installer, either for direct download (and notarization) or validation and upload to app store.

@HealsCodes
Copy link

HealsCodes commented Oct 27, 2022

Update - more research - still not QSingleApplication's fault; Qt has a number of "specialities" for Apple & the Mac AppStore:

I don't need to do any of that normally. The Koord app has been building and running fine for ages, and also accepted without problem into App store. None of the links you specified are necessary. I certainly don't need to build Qt6 myself to create a working Mac installer, either for direct download (and notarization) or validation and upload to app store.

Well.. your binary is completely valid and thus can be code-signed and uploaded to the mac-appstore, but the shared memory QSingleApplication uses won't work because it does not follow the requirements for sandboxed applications.
This is a runtime-requirement, so it doesn't trip anything during Apple's validations as they don't run the binaries when notarising but only scan symbols and signatures.

@danryu
Copy link

danryu commented Oct 27, 2022

@itay-grudev
Seems like @Shirk has isolated the issue, has an M1 Mac and is willing to run test builds :)
Do we have the elements to potentially implement a fix?

@itay-grudev itay-grudev reopened this Oct 27, 2022
@itay-grudev
Copy link
Owner

@danryu

The only thing I can do is to address the following points:

  • The key must be in the form <application group identifier>/<custom identifier>, as documented here and here.
  • The key length is limited to 30 characters.

Currently the shared memory uses the following as a key:

void SingleApplicationPrivate::genBlockServerName()
{
QCryptographicHash appData( QCryptographicHash::Sha256 );
#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
appData.addData( "SingleApplication", 17 );
#else
appData.addData( QByteArrayView{"SingleApplication"} );
#endif
appData.addData( SingleApplication::app_t::applicationName().toUtf8() );
appData.addData( SingleApplication::app_t::organizationName().toUtf8() );
appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() );
if ( ! appDataList.isEmpty() )
appData.addData( appDataList.join(QString()).toUtf8() );
if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ){
appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() );
}
if( ! (options & SingleApplication::Mode::ExcludeAppPath) ){
#if defined(Q_OS_WIN)
appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() );
#elif defined(Q_OS_LINUX)
// If the application is running as an AppImage then the APPIMAGE env var should be used
// instead of applicationPath() as each instance is launched with its own executable path
const QByteArray appImagePath = qgetenv( "APPIMAGE" );
if( appImagePath.isEmpty() ){ // Not running as AppImage: use path to executable file
appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() );
} else { // Running as AppImage: Use absolute path to AppImage file
appData.addData( appImagePath );
};
#else
appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() );
#endif
}
// User level block requires a user specific data in the hash
if( options & SingleApplication::Mode::User ){
appData.addData( getUsername().toUtf8() );
}
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
// server naming requirements.
blockServerName = QString::fromUtf8(appData.result().toBase64().replace("/", "_"));
}
void SingleApplicationPrivate::initializeMemoryBlock() const
{
auto *inst = static_cast<InstancesInfo*>( memory->data() );
inst->primary = false;
inst->secondary = 0;
inst->primaryPid = -1;
inst->primaryUser[0] = '\0';
inst->checksum = blockChecksum();
}

This code basically computes a hash based on the input data for single application (like application name, organisation, username, etc.) and computes a hash to be used as a shared memory identifier. I suppose we will have to use a different one that follows the scheme specified above.

Just one question - is the <application group identifier> something Apple assigns developers or could it be arbitrary?

@danryu
Copy link

danryu commented Oct 27, 2022

Just one question - is the <application group identifier> something Apple assigns developers or could it be arbitrary?

I'm not 100% on this - but I think the application group identifier corresponds to the PRODUCT_BUNDLE_IDENTIFIER which in the case of Koord is live.koord.Koord-RT.
https://doc.qt.io/qt-6/qmake-variable-reference.html#qmake-info-plist

(I think the Team-id is an alphanumeric token which Apple applies automatically in App Store Connect.)

@HealsCodes
Copy link

HealsCodes commented Oct 28, 2022

Just one question - is the <application group identifier> something Apple assigns developers or could it be arbitrary?

I'm not 100% on this - but I think the application group identifier corresponds to the PRODUCT_BUNDLE_IDENTIFIER which in the case of Koord is live.koord.Koord-RT. https://doc.qt.io/qt-6/qmake-variable-reference.html#qmake-info-plist

It doesn't - that's your application identifier, the application group identifier is something you create separately here:

Screenshot 2022-10-28 at 09 49 49@2x

App Groups always start with a "group." prefix

You have to enable "App Groups" when creating the application identifier for you app and then select the group in order for the app to be allowed access: (also here)

Screenshot 2022-10-28 at 09 51 49@2x

Screenshot 2022-10-28 at 09 58 04@2x

(I think the Team-id is an alphanumeric token which Apple applies automatically in App Store Connect.)

Correct, you get assigned one Team-ID per account. It is randomly generated by Apple but does not change between applications.

There's no way - I'm aware of - for QSingleApplication to determine these values other than the developer providing them at configuration time or via preprocessor defines.

I hope this info helps.

@danryu
Copy link

danryu commented Oct 28, 2022

Many thanks @Shirk - this is indeed very helpful.
I'll go ahead and create the Application Group as advised.

There's no way - I'm aware of - for QSingleApplication to determine these values other than the developer providing them at configuration time or via preprocessor defines.

That I can do fairly easily I suppose. Not sure @itay-grudev how best this could/would be integrated with SingleApplication?

(PS Apple certainly don't make it easy in this case do they? But I guess this support will only be more necessary in the future as Intel builds get phased out...)

@HealsCodes
Copy link

Many thanks @Shirk - this is indeed very helpful. I'll go ahead and create the Application Group as advised.
You're welcome

(PS Apple certainly don't make it easy in this case do they? But I guess this support will only be more necessary in the future as Intel builds get phased out...)

Yeah, they have most of it fully automated if you use XCode which even manages application IDs, group identifiers and signing entitlements for you but if you don't want to or can't use XCode it's a lot of documentation and forum knowledge to absorb and a lot of trial and error involved.

(I only learned most of those things in the first place because it equally applies to iOS and has for years)

@danryu
Copy link

danryu commented Nov 2, 2022

Well, I've tried all the steps advised, but I still can't get it to work :(
The app crashes still startup with this message:

SingleApplication: Unable to create block.
SingleApplication:  1 "QSharedMemoryPrivate::initKey: unable to set key on lock"

Steps followed:

  • built Qt 6.3.2 for Mac with Posix compliance (script here)
  • created Application Group Id group.koord in Apple Developer Center
  • set
    blockServerName = "TXZ4FR95HG.koord/shared";
    in singleapplication_p.cpp to override the logic in genBlockServerName()
    and to follow the pattern of
    QSharedMemory shm("DEVTEAMID.app-group/shared");
    given at https://doc.qt.io/qt-6/qsharedmemory.html#details.

It's not yet clear to me from all the docs linked whether I have done everything right - in particular I'm not sure whether to use the "group." prefix on the Application Group id. It gets added automatically in Developer Center, but the Apple docs here suggest not to use it. I may be wrong though.

Any help appreciated!

image

@HealsCodes
Copy link

Well, I've tried all the steps advised, but I still can't get it to work :( The app crashes still startup with this message:

SingleApplication: Unable to create block.
SingleApplication:  1 "QSharedMemoryPrivate::initKey: unable to set key on lock"

Steps followed:

  • built Qt 6.3.2 for Mac with Posix compliance (script here)
  • created Application Group Id group.koord in Apple Developer Center
  • set
    blockServerName = "TXZ4FR95HG.koord/shared";
    in singleapplication_p.cpp to override the logic in genBlockServerName()
    and to follow the pattern of
    QSharedMemory shm("DEVTEAMID.app-group/shared");
    given at https://doc.qt.io/qt-6/qsharedmemory.html#details.

It's not yet clear to me from all the docs linked whether I have done everything right - in particular I'm not sure whether to use the "group." prefix on the Application Group id. It gets added automatically in Developer Center, but the Apple docs here suggest not to use it. I may be wrong though.

You are correct, the docs state that the "group" prefix is only required on iOS, your TXZ4FR95HG.koord/shared looks fine to me. As does the group selection. Just to make sure, did you recreate and re-download the signing profile for the App-ID afterwards? (My terms might be a bit off, for iOS your signing certificates are paired with a provisioning profile which in turn is bound to the application ID and links it to details like allowed application groups. It feels like you do everything correctly bu t macOS just doesn't know your app belongs into that group because it can't link it to a provisioning see here)

@danryu
Copy link

danryu commented Nov 2, 2022

Thanks @Shirk. I did re-create the iOS provisioning profile, but not yet for macOS. I will do this - but also need to remind myself how to apply the provisioning profile during the build with Qt. Not sure if I can use any options in macdeployqt or productbuild to do this...

@danryu
Copy link

danryu commented Nov 3, 2022

Well, this has got me beaten. I can't get past the error on startup.
Steps:

  • created new Developer ID Application type certificate
  • created new provisioning profile for this certificate
  • applying secrets in build setup as per github docs

The best info I could find online regarding how to apply the provisioning profile on MacOS was here
But really the documentation for this is barely existent!

So I apply the file embedded.provisionprofile to the /Koord.app/Contents/ before codesigning and packaging.
The build completes successfully, and .pkg build also validates and uploads to the App Store fine. (Haven't tested that build yet.)

But the dmg installer (Koord_4.0.23.dmg) still results in a broken installation, with the app failing to start.

I'm at a loss what to do now - I wanted to maintain the App Store presence of the app, but if I do this now I have to create build-time or run-time flags to avoid using SingleApplication when building for / running from an App Store build.

@HealsCodes
Copy link

Well, this has got me beaten. I can't get past the error on startup. Steps:

  • created new Developer ID Application type certificate
  • created new provisioning profile for this certificate
  • applying secrets in build setup as per github docs

The best info I could find online regarding how to apply the provisioning profile on MacOS was here But really the documentation for this is barely existent!

So I apply the file embedded.provisionprofile to the /Koord.app/Contents/ before codesigning and packaging. The build completes successfully, and .pkg build also validates and uploads to the App Store fine. (Haven't tested that build yet.)

But the dmg installer (Koord_4.0.23.dmg) still results in a broken installation, with the app failing to start.

I'm at a loss what to do now - I wanted to maintain the App Store presence of the app, but if I do this now I have to create build-time or run-time flags to avoid using SingleApplication when building for / running from an App Store build.

Hmm, attempting to dump your embedded.provisionprofile gives me an ad-hoc profile, that might be the issue (I'm sorry I'm not more helpful):
Screenshot 2022-11-03 at 14 25 03@2x

@danryu
Copy link

danryu commented Nov 3, 2022

I call it "adhoc" to distinguish from the "store" certificates and profiles.
But the certificate type is definitely Developer ID Application as advised in the docs.

@danryu
Copy link

danryu commented Nov 3, 2022

The Problem is also not with QSingleApplication but rather with your codesigning entitlements which prevent shared memory usage, which in turn causes QSharedMemoryPrivate::initKey to fail.

Hang on, just checking this - which "codesigning entitlements" are causing QSharedMemoryPrivate::initKey to fail?

The dmg installer is not signed with anything appstore-specific, nor is there any sandboxing involved as far as I know.
https://doc.qt.io/qt-6/qsharedmemory.html#details

The .app package is built and signed like so:

    macdeployqt "${build_path}/${target_name}.app" \
        -verbose=2 \
        -always-overwrite \
        -sign-for-notarization="${macadhoc_cert_name}" \
        -qmldir="${root_path}/src"

This does not involve the -appstore-compliant option which is required for appstore submission.

So now I'm really confused. I can't see why this error is still happening.

@danryu
Copy link

danryu commented Nov 4, 2022

OK - finally - I got past the error.

I had this bit of cruft in my .entitlements file (which gets included in qmake project).

	<key>com.apple.security.app-sandbox</key>
	<true/>

Which meant that the dmg installer was getting built with that constraint, despite it not being necessary.
After removing that from the entitlements file, the dmg-installed app runs fine. (Phew!)

I now use a POSIXMAC define at compile stage to switch between no use of SingleApplication (for AppStore) and using SingleApplication (for dmg installer). This is annoying, as it means I now have differing feature sets between the two versions...

At some point, somebody else out there will hopefully resolve this AppStore-compliance issue with SingleApplication/QSharedMemory! Until then all users installing from the App Store will get confusing multiple instances of our app.

It feels like this shouldn't be such a rare use case!

  • Qt app on current macOS - not that unusual
  • building for AppStore - not that unusual
  • using SingleApplication (which is so useful that it's weird it's not in mainline Qt)

And yet despite rebuilding Posix-compliant Qt from scratch, setting up app ids, app group ids, certificates and provisioning profiles, and patching singleapplication_p.cpp with the correct key for share memory - it still won't work! :/

Note: perhaps this should be logged in a separate issue, as this does not have anything to do with Apple M1

@itay-grudev
Copy link
Owner

This is indeed a terrible experience, but I don't know I can do in this case.

The only change SingleApplication can do is implement a function: SingleApplicationPrivate::sharedMemoryKey() that simply returns genBlockServerName except on MacOS, where it follows the MacOS format.

But based on your experiments, that still wouldn't work.

@danryu
Copy link

danryu commented Nov 6, 2022

Thanks @itay-grudev, that itself would be a useful change, as it would save me forking SingleApplication or doing nasty build-time patches :)

I guess this is a potential bug to log with Qt? I'm a little wary of doing that myself as it's on the boundaries of my Qt knowledge so I won't be that useful when interrogated by Qt devs in the issue thread!

@itay-grudev
Copy link
Owner

itay-grudev commented Nov 6, 2022 via email

@HealsCodes
Copy link

HealsCodes commented Nov 6, 2022

Just make sure you provide them with a minimal example reproducing the problem. And don't worry, they are pretty good at ignoring non-paying customers.

Can confirm, I have a history with filing bugs with them - even actual broken core functionality in their less used modules and the average turn-around for a "not my problem" reply is 6-8 months.

Provide that minimal example and a clear explanation of what you did, expected and what actually happened; link this issue if you want or at least the guides from Apple and then that's all you can really do honestly.

Better to write it and leave a pesky reminder for Qt than have the knowledge go to waste.
Usually if I have issues like that my first go-to is bugreports.qt.io to check if it's a known issue.

@danryu
Copy link

danryu commented Nov 8, 2022

Just make sure you provide them with a minimal example reproducing the problem.

Creating a minimal example which demonstrates the issue out of the box is fairly tricky.
Any of the SingleApplication examples would work fine for this. But they have as prequisite:

  • Qt compiled app-store compliant (posix) - I can link to my release build I guess
  • AppStore Connect resources:
    • Developer ID Application certificate
    • Application ID
    • Application Group ID
    • Provisioning Profile

Do you think I have to detail all these steps as well - or can I assume a Qt Mac developer has XCode set up already to accommodate this stuff?

@HealsCodes
Copy link

Do you think I have to detail all these steps as well - or can I assume a Qt Mac developer has XCode set up already to accommodate this stuff?

Point them to their own documentation - they should know what they wrote themselves on POSIX / AppStore compliant builds.
As for the Apple signing stuff, tell them they need the points you listen and which permissions/entitlements.
They should be able to reproduce it as they have mac developers there.

@danryu
Copy link

danryu commented Nov 9, 2022

Thanks for the tips @Shirk @itay-grudev
Qt bug created here: https://bugreports.qt.io/browse/QTBUG-108283

@danryu
Copy link

danryu commented Dec 3, 2022

FYI @Shirk @itay-grudev
The above issue is resolved.
I just had to add the following to the app.entitlements file that gets fed to QMAKE_BUNDLE_DATA/QMAKE_MAC_XCODE_SETTINGS during the CI build process.

<key>com.apple.security.application-groups</key>    
<string>MYTEAMID.mygroup</string>

This is using Qt 6.4.1 configured and built for Universal (x86_64, arm64) with -appstore-compliant.

The only thing is that I have to patch singleapplication_p.cpp during the CI build to override the blockServerName assignment.
How could this be streamlined?

@itay-grudev
Copy link
Owner

Can you share your changes and I'll incorporate them.

@danryu
Copy link

danryu commented Dec 3, 2022

This is the patch I apply to SingleApplication:
https://github.com/koord-live/koord-app/blob/main/mac/macOS_posix.patch
(it's this bit that would be good if it was configurable at build time)

This is the according change I had to make to entitlements file:
https://github.com/koord-live/koord-app/blob/1284871bea43993139522069a6276caef18cbf47/mac/Koord.entitlements#L19-L20

@HealsCodes
Copy link

HealsCodes commented Dec 3, 2022

That should be doable with a CMake option or variable and turning singleapplication_p.cpp into a template you shove through configure_file() I believe?

Or just having the Shared-memory ID in an #ifndef like:

#if defined ( Q_OS_MACOS )
#ifndef MAS_TEAM_ID
# define MAS_TEAM_ID "single-app-default"
#endif 
    // need to overwrite for macOS - app store - POSIX shmem requirements
    blockServerName = MSA_TEAM_ID "/shared";
#endif

That way the user could easily set it at configure-time with a compiler define (-DMAS_TEAM_ID="12345abc.team").

@itay-grudev
Copy link
Owner

itay-grudev commented Dec 3, 2022

It's my opinion that the entitlements file should be managed by the developer and not by SingleApplication, but the other patch I will apply. I will do it differently though, as currently the blockServerName is used for both QSharedMemory and QLocalServer - I will differentiate them with a serverName and sharedMemoryName.

The check will be only for MacOSX and I will need to add an extra method to SingleApplication akin to setOrganizationName() for setAppleTeamId.

The final sharedMemoryName will be generated from the application name and team id.

@danryu
Copy link

danryu commented Dec 4, 2022

@itay-grudev This sounds great.

I'm just wondering about this bit though:

The final sharedMemoryName will be generated from the application name and team id.

The required format seems to be
"<team_id>.<application_group_id>/shared"

where application_group_id is set as so in Apple Developer account:
image

As such, the app name and application group ID are not necessarily the same - although I made it the same in this case for simplicity and brevity (to stay under the char limit).
As the application_group_id is passed in the entitlements file (which I included just as an example of my configuration btw), which is ingested during the project configuration, would it be possible to pull that value from that project conf at build time?

@itay-grudev
Copy link
Owner

We are aware of multiple issues with Qt's latest implementation of QSharedMemory and QSystemSemaphore and even the latter is not truly thread safe. We are working on an implementation that would rely on a different mechanism - QLocalSockets but the development is still in-progress.

I'll close this issue for now as we no longer plan to work in the direction of QSharedMemory.

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

4 participants