You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I’m debugging thread safety in OCMock 3 and have an example test case that demonstrates some faulty behavior. In short, it looks like invoking a class method from a background thread while a class mock is being restored causes crashes due to unrecognized selectors.
Strangely, this isn’t a problem with OCMock 2. I suspect 1ad7292 may have something to do with it.
I realize this is a contrived example, but it’s flaky enough to prevent me from upgrading my project from v2 to v3.
I just hit this same issue, with OCMock 3.3 (which the release notes claims makes mocking thread-safe).
I believe the root issue here is OCMock's class mocking isa-swizzles the metaclass prior to installing methods. This means that background threads may start interacting with the metaclass while it's in the process of installing methods, which is pretty bad.
Since I'm not sure if moving the metaclass swizzle to the end is safe (I don't know if any of the intervening code relies on it already being installed), I believe a safe fix is to reorder two lines in -setupForwarderForClassMethodSelector::
@erikdoe I assume you're getting notifications for issue updates anyway, but just in case, I'm mentioning you as this is a nasty issue that has been causing spurious test failures for us for a long time and I'm surprised that this ticket never got a response.
@erikdoe Can you please take a look at this? It's a real issue with a trivial fix.
FWIW, it turns out that uninstalling class mocks isn't thread safe either, which doesn't seem to be a solvable short of simply never destroying the dynamically-created class pairs, but in my experience the uninstall issue crops up a lot less frequently than the install issue did.
Sorry. I should have responded earlier. My concern is that the failing test provided in the issue tests a scenario that, as far as I can tell, cannot be supported by OCMock. It has always been clear that OCMock is only thread-safe to a certain degree. Repeatedly calling a method while setting up and removing a mock would, as far as I am aware, require most of the operations on the class to be atomic, and I don't see a way how to achieve this.
The fix provided by @kballard looks benign, but it doesn't fix the issue reported. In fact, there is no test that I can think of that would fail without the change but pass with it. That said, the change is small and it feels like it brings the two operations into a "more correct" sequence. So I have accepted it now.
Activity
lilyball commentedon Jan 9, 2018
I just hit this same issue, with OCMock 3.3 (which the release notes claims makes mocking thread-safe).
I believe the root issue here is OCMock's class mocking isa-swizzles the metaclass prior to installing methods. This means that background threads may start interacting with the metaclass while it's in the process of installing methods, which is pretty bad.
lilyball commentedon Jan 9, 2018
Since I'm not sure if moving the metaclass swizzle to the end is safe (I don't know if any of the intervening code relies on it already being installed), I believe a safe fix is to reorder two lines in
-setupForwarderForClassMethodSelector::lilyball commentedon Jan 9, 2018
@erikdoe I assume you're getting notifications for issue updates anyway, but just in case, I'm mentioning you as this is a nasty issue that has been causing spurious test failures for us for a long time and I'm surprised that this ticket never got a response.
lilyball commentedon Oct 18, 2018
@erikdoe Can you please take a look at this? It's a real issue with a trivial fix.
FWIW, it turns out that uninstalling class mocks isn't thread safe either, which doesn't seem to be a solvable short of simply never destroying the dynamically-created class pairs, but in my experience the uninstall issue crops up a lot less frequently than the install issue did.
Partial fix for #328.
erikdoe commentedon Oct 22, 2018
Sorry. I should have responded earlier. My concern is that the failing test provided in the issue tests a scenario that, as far as I can tell, cannot be supported by OCMock. It has always been clear that OCMock is only thread-safe to a certain degree. Repeatedly calling a method while setting up and removing a mock would, as far as I am aware, require most of the operations on the class to be atomic, and I don't see a way how to achieve this.
The fix provided by @kballard looks benign, but it doesn't fix the issue reported. In fact, there is no test that I can think of that would fail without the change but pass with it. That said, the change is small and it feels like it brings the two operations into a "more correct" sequence. So I have accepted it now.