Dynamic library unable to be loaded after recompile, crashes with Code Signature Invalid

I am developing a postgres extension. This means that I am compiling a dynamic library which is loaded at runtime by the postgres application (with dlopen).

Ever since switching to a new mac with the M1 Pro and Monterey, I've been having trouble with the dynamic library load occasionally (but seemingly repeatably) crashing the process. The error that I get in the crash report is:

Exception Type:        EXC_BAD_ACCESS (SIGKILL (Code Signature Invalid))
Exception Codes:       UNKNOWN_0x32 at 0x000000010c8f8000
Exception Codes:       0x0000000000000032, 0x000000010c8f8000
Exception Note:        EXC_CORPSE_NOTIFY

The top of the stack trace tells me that this is failing in the dyld3 code:

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   dyld                          	       0x102cb62c8 dyld3::MachOFile::compatibleSlice(Diagnostics&, void const*, unsigned long, char const*, dyld3::Platform, bool, dyld3::GradedArchs const&) + 76

When I validate the code signature using codesign, it appears to be valid:

codesign --verify --verbose /Users/me/.pgx/14.1/pgx-install/lib/postgresql/my-extension.so
/Users/me/.pgx/14.1/pgx-install/lib/postgresql/my-extension.so: valid on disk
/Users/me/.pgx/14.1/pgx-install/lib/postgresql/my-extension.so: satisfies its Designated Requirement

The steps that I take to reproducibly cause this error are the following:

  • Compile extension
  • Run postgres
  • Trigger dynamic library load (successfully)
  • Make a small code change to the extension
  • Recompile extension
  • Trigger dynamic library load (unsuccessfully)

It may be an important detail that due to how the build system works, the "recompile extension" step actually consists of:

  • recompile extension to /foo/bar/my-extension.dylib
  • copy /foo/bar/my-extension.dylib to /Users/me/.pgx/14.1/pgx-install/lib/postgresql/my-extension.so

The reason this may be noteworthy is that the inode number of /Users/me/.pgx/14.1/pgx-install/lib/postgresql/my-extension.so remains the same.

I can work around this issue by first removing /Users/me/.pgx/14.1/pgx-install/lib/postgresql/my-extension.so and then copying /foo/bar/my-extension.dylib to /Users/me/.pgx/14.1/pgx-install/lib/postgresql/my-extension.so.

Note: I am not explicitly signing the library, this is being done automatically by the compiler.

Due to the steps to reproduce, and the workaround mechanism, my suspicion is that there is some sort of signature caching mechanism which tries to compare either the old signature with the new file, or vice-versa.

I would appreciate any help in further debugging this issue, and I am happy to provide further information where necessary.

Accepted Reply

Based on your thorough description of the issue (thanks!) I’m almost certain you’re hitting the issue discussed in Updating Mac Software.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Replies

Based on your thorough description of the issue (thanks!) I’m almost certain you’re hitting the issue discussed in Updating Mac Software.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"