If Objective-C isn't available, than forking will not be effected.
MAC OS HIGH SIERRA COMPATIBILITY ISSUES CODE
The code doesn't check for errors, because a quite failure doesn't effect behavior. The _APPLE_ directive will only work on gcc (gnu compiler), clang and intel compilers (other compilers might be supported, but I don't know). * iodine runs here and `fork` might be called */ #endif
Void * obj_c_runtime = dlopen ( "amework/Foundation", RTLD_LAZY ) /* iodine runs here and `fork` might be called */ dlclose ( obj_c_runtime ) #else This is the C code I'm currently considering for the iodine Ruby server.
I should point out that "amework/Foundation" seems to be enough. But I do believe that having a workaround inside Ruby is an essential part of the entire fix, because updating all gems takes a lot of time and effort. In order to fully fix the problem, cooperation from the wider Ruby community is required: all the gem authors will also have to ensure that native libraries don't spawn any threads until the app server has forked. Adding a workaround in Ruby (in the form of ensuring that Objective-C initializers are called before forking) will at least ensure that we return to pre-High Sierra behavior.Īdding a workaround inside Ruby would only be a part of the whole solution. But all these factors combined make less sense. Set a breakpoint on objc_initializeAfterForkError to debug.īy itself, Apple's error check makes sense. We cannot safely call it or ignore it in the fork() child process. Objc: + may have been in progress in another thread when fork() was called. The new Apple-enforced rule checks then abort the process with a warning like this:.
Due to how these gems are used, it can occur that these gems end up calling Objective-C initializers after the app server has forked.
The workaround (specific to Puma’s DSL) was: # Work around macOS 10.13 and later being very picky about # `fork` usage and interactions with Objective-C code # see: if /darwin/ =~ RUBY_PLATFORM before_fork do require 'fiddle' # Dynamically load amework, ~implicitly~ initialising # the Objective-C runtime before any forking happens in Puma Fiddle. This causes forked processes using other Objective-C APIs to not crash. This includes Puma, Unicorn, iodine and Passenger.Ī workaround I proposed for Puma was to implicitly load the Objective-C runtime before performing any forks ( ). This means that many applications which use forking to process concurrently will forcibly crash if the forked process calls out to any Objective-C library when Objective-C was not already initialised in the host process. MacOS High Sierra has changed the behaviour of the fork syscall such that initialising Objective-C APIs in forked processes are treated as errors. This was originally discussed on the issue tracker for Puma ( ), however, it is possible that it would make more sense for inclusion in the Ruby implementation itself.