macOS Mojave

Apple is due to release its latest upgrade to macOS today. Most interestingly, it adds a dark mode, where all your windows get a dark background and white text. I expect some will like it and others will not. The major issue of course will be compatibility: apps that where built with support for dark mode will work, others will not. So you’ll need to update all your apps or tolerate a mix of dark and light windows.

What about the apps I publish? Black Light, Black Light Pro, Gamma Control, and Counterparts Lite are all ready, just make sure you have the latest update I released earlier today. I’ll have updates to Sim Daltonism and Red Stripe ready a bit later this week, but since the main window border is already translucent dark, this is mostly to get the preferences window to support dark mode.

So feel free to upgrade to Mojave and enjoy the dark mode (if that’s your thing). But I’ll also continue to support older macOS versions for a couple of years so don’t worry if you can’t or don’t want to upgrade right now.

Other fixes

The new releases of Black Light and Gamma Control will also fix a problem that could occur during screen reconfigurations, when plugging a new monitor or a dual GPU MacBook Pro switched GPU. The effect on the gamma curve would be applied twice, resulting generally in something darker. The way to extract the base gamma curve has changed and should be more stable now.

Black Light Pro (launched last week) already had support for dark mode. The 1.0.1 version fixes an issue where fading transitions wouldn’t work correctly in some situations.

The Counterparts Lite update fixes an issue where clicking on a text cell and quickly typing could result in the first typed character being deleted.

Black Light Pro

Here comes a more advanced version of Black Light.

Wouldn’t it be cool if Black Light was able to change its effect as time passes on? Or how about applying a different effect on each screen? Maybe some apps are playing tricks and temporarily resetting the effect, dazzling your eyes with “normal colors” you’d rather not see.

Those are the problems Black Light Pro should help you with. It’s an entirely new version of Black Light that can do much more:

  • Multiple effects
  • Each screen can have its own effect
  • Hot key for each effect
  • Custom activation and deactivation time for each effect
  • Can use sunset or sunrise as activation or deactivation time
  • Smooth transitions with custom transition duration that can differ for manual and timer actions

The preference window should give you an idea of what’s possible:

This new Pro version applies its effect using a color profile, meaning colors are much less at risk of being temporarily reset by another app. When doing astronomy or running a grading suite, this can be important. This takes more CPU however, so if you find your computer is suddenly laggy after a transition, feel free to deactivate the Apply Effect to Color Profile checkbox.

Black Light Pro is not available in the Mac App Store. The reason: the sandbox does not allow setting a color profile. If the sandbox allows setting a color profile in the future, I’ll probably make it available there, but for now you’ll have to purchase from this website.

Download Black Light Pro to get a free 30-day trial. You can purchase it at $24.99 USD when you’re ready.

Note: the regular version of Black Light remains available for those who do not need all the fanciness of the Pro version.

Slow load time, code signing, and the sandbox container

I had a bizarre slow loading problem with a Mac app. Before reaching main, while loading the libraries, the process stalls for about 20 seconds. By adding DYLD_PRINT_STATISTICS=1 to the environment variables, I can get the dynamic linker to print statistics about loading, which reveals this ridiculous delay in initializing libSystem.B.dylib:

Total pre-main time: 22.6 seconds (100.0%)
         dylib loading time: 167.96 milliseconds (0.7%)
        rebase/binding time:  15.58 milliseconds (0.0%)
            ObjC setup time:  15.36 milliseconds (0.0%)
           initializer time: 22.4 seconds (99.1%)
           slowest intializers :
             libSystem.B.dylib : 22.4 seconds (98.9%)

Stopping the process during that time (which is easy, you have a 20 second window to do it) reveals this backtrace that looks like an initializer is waiting for some response from an XPC service:

Binary Function
0 libsystem_kernel.dylib mach_msg_trap
1 libsystem_kernel.dylib mach_msg
2 libxpc.dylib xpc_pipe_routine
3 libsystem_secinit.dylib _libsecinit_send_request
4 libsystem_secinit.dylib _libsecinit_setup_secinitd_client
5 libsystem_secinit.dylib _libsecinit_initialize_once
6 libdispatch.dylib _dispatch_client_callout
7 libdispatch.dylib dispatch_once_f
8 libSystem.B.dylib libSystem_initializer
9 dyld ImageLoaderMachO::doModInitFunctions
10 dyld ImageLoaderMachO::doInitialization
11 dyld ImageLoader::recursiveInitialization
12 dyld ImageLoader::recursiveInitialization
13 dyld ImageLoader::processInitializers
14 dyld ImageLoader::runInitializers
15 dyld dyld::initializeMainExecutable
16 dyld dyld::_main
17 dyld dyldbootstrap::start
18 dyld _dyld_start

Inspecting the stack trace, it appears libsystem_secinit is responsible for the XPC request.

Meanwhile, looking at the console, I see about a thousand of identical messages like this one every time I launch the app:

secinitd: MacOS error: -67050

Obviously the secinitd deamon is doing a job on behalf of the libsystem_secinit library and something fails… a thousand times!

So far so good, but what does this error mean? A quick search for error -67050 says errSecCSReqFailed, or “The code failed to satisfy one of the code requirements.”

Even though it doesn’t really say “code signing” anywhere, this message is reminiscent of code signing issues since it talks about “code requirements”. This feeling is somewhat amplified by the name “secinit” that looks like a shorthand for “security” and “initialization”.

The app’s code is signed by Xcode at build time, so it should be fine. But opening it with RB App Checker Lite reveals a peculiarity: “The application was signed by an unidentified entity (this is unusual).” What does that mean? Does it have something to do with the current issue?

Meanwhile, I tested the app on other computers. It ran fine everywhere with no delay at startup. Even on my development machine, if I ran the app in another user account everything was fine. It definitely had something to do with my user account.

Not really knowing where to start looking, I changed the bundle ID of the app. Oh, now it launches instantly! Going back to the old bundle ID, the 20-second loading problem comes back. So it is somehow linked to the bundle ID.

Now I know I need to look for something that has the bundle ID in my user account. My first stop is the “~/Library/Containers” folder. Every sandboxed app automatically get a container where it can put its files and settings, and the container’s name is the app’s bundle ID. I move the app’s container folder away and relaunch, and… oh, it’s fast again!

That container definitely has something to do with the problem. So I restore the old container and look for something suspicious inside. There’s not much in there beside mostly empty folders and symlinks. But there’s a Container.plist file at the root of the container that looks interesting.

Inside Container.plist, there’s a Version number and there’s an Identity array. That Identity array has 7313 data items in it. Each item is different, but they all look somewhat like this:

<fade0c00 00000048 00000001 00000007 00000008 00000014
 8254e67a 5efbb500 2eef7741 b8bc6054 18cc5224 00000008
 00000014 d025ece1 ac627aae 27d047b0 deaa1450 6563b718>

I don’t know exactly what they are, but looking at containers for other apps I can see one, two, or three identities at most. Never something in the thousands. That’s suspicious.

I delete the Identity array and run the app again. And it loads fast. And a new identity also appears in Container.plist without me doing anything beside launching the app. Running the app a second time does not make a new identity appear. But then I tried build and run from Xcode: a new identity would appear. If every time I build and run a new identity appears, that’d explain the huge number.

Here’s my guess at what’s happening. The identity corresponds to whoever signed the app, something linked to the signing certificate. Upon launching the app, the sandbox adds that identity to Container.plist (unless the identity is already there) to keep track of who ran with this container. Now, remember RB App Checker Lite seeing the app as signed by an “unidentified entity”? Perhaps this translates somehow as a new identity every time the app is built.

Once the array is bloated with too many identities, the secinitd daemon becomes very slow at whatever it is doing. By the repeated errors to “errSecCSReqFailed” on the console, I’d adventure a guess at saying it reverifies the app signature for each and every identity found in Container.plist. It’d make sense that recomputing the checksum 7313 times would take more than 20 seconds and spill thousands of MacOS error: -67050 to the system console.

Knowing that I can periodically clean the Container.plist, while reassuring, is not very satisfactory. What is causing this signature issue the first place?

After looking at all the build settings for this project, I ended up noticing signing was not enabled for the test bundle target that contains all the unit tests.

I enabled signing for the test bundle. Doing this makes RB App Checker Lite see a proper signing identity for the app. Building and running the app a couple times is no longer adding a new identity every time. So problem solved!

Why would secinitd add a new identity every time the app is built though? Something must change for the identity to change, right? I believe it happens because I have a script bumping the build number every time I build. Disabling this script (keeping the build number the same for every build) stops new identities from appearing. This seems to confirm that identities are dependent on the build number when the signature is from an “unidentified entity”.

Note that having about 7313 identities in Container.plist will slow things down regardless of whether your build number is the same or not, or your signature is form an “unidentified entity” or not. So it’s still important to cleanup Container.plist to get normal loading times again after fixing this signing problem. Here’s the final times:

Total pre-main time: 307.72 milliseconds (100.0%)
         dylib loading time: 157.79 milliseconds (51.2%)
        rebase/binding time:   2.66 milliseconds (0.8%)
            ObjC setup time:   9.39 milliseconds (3.0%)
           initializer time: 137.63 milliseconds (44.7%)
           slowest intializers :
             libSystem.B.dylib : 123.46 milliseconds (40.1%)

307.72 milliseconds is a 7344 % improvement over 22.6 seconds!

(This is on macOS High Sierra. I haven’t tested if Mojave still exhibit this problem.)

Groups in Gamma Board

Gamma Board lets you adjust the gamma settings for screens remotely, which is nice in a studio because you can tweaks the colors from a distance while seeing the whole picture. But if you have a lot of screens to color-manage, it can still be tedious to adjust each of them individually for every change in surrounding lighting.

This is what groups aims to solve. You can still tweak each screen individually as before, but starting in version 1.2 screens also belong to a group. A group has gamma settings similar to screens, but group settings apply to all screens in the group. Group settings are merged with the individual settings for each screen, and the final result is sent to the computer that controls each screen.

A new set document (or a set imported from a previous version) will start with one “main group” that contains all the screens. You can create new groups as needed by tapping the “+” button in the toolbar below the list of screen and choosing “Add Group”. You can move screens between groups the same way you can reorder screens: using drag & drop.

Gamma Board 1.2 is available on the App Store. Customers with a branded version can request an update to the customized app.

  • © 2003–2018 Michel Fortin.