Crash from OnBeforeSerialize

using Unity 2020.3.25f1

so, I do some postprocessing (basically find and auto link/collect components) in the OnBeforeSerialize and sometimes I get a crash similar to this one. any ideas why?

Reloading assemblies after forced synchronous recompile.
Begin MonoManager ReloadAssembly
Obtained 44 stack frames.
#0 0x0000014f50601b in mono_class_init
#1 0x0000014f50ffba in mono_class_is_subclass_of
#2 0x0000010df378af in scripting_class_has_parent(ScriptingClassPtr, ScriptingClassPtr)
#3 0x0000010df29a2a in bool GetComponentsImplementation<false, 1>(GameObject&, bool, CompareParameters const&, GetComponentsImplementation_ReturnValue const&)
#4 0x0000010df2a40d in bool GetComponentsImplementationRecurse<false, 0, 1>(GameObject&, bool, CompareParameters const&, GetComponentsImplementation_ReturnValue const&, ScriptingExceptionPtr*)
#5 0x0000010df2568e in ScriptingGetComponentsOfTypeFromGameObject(ScriptingGetComponentsArgs const&, ScriptingExceptionPtr*)
#6 0x0000010e099afc in GameObject_CUSTOM_GetComponentsInternal(ScriptingBackendNativeObjectPtrOpaque*, ScriptingBackendNativeObjectPtrOpaque*, unsigned char, unsigned char, unsigned char, unsigned char, ScriptingBackendNativeObjectPtrOpaque*)
#7 0x0000018208578e in (wrapper managed-to-native) UnityEngine.GameObject:GetComponentsInternal (UnityEngine.GameObject,System.Type,bool,bool,bool,bool,object) {0x7fa519fa1eb8} + 0xfe (0x182085690 0x182085842) [0x14fac9960 - Unity Child Domain]
#8 0x00000183d512bb in UnityEngine.GameObject:GetComponentsInChildren<T_REF> (bool) {0x7fa49b0307c0} + 0xcb (0x183d511f0 0x183d5132d) [0x14fac9960 - Unity Child Domain]
#9 0x00000183d50c53 in XXXXX:OnBeforeSerialize () {0x7fa4ade72fc0} + 0xc53 (0x183d50000 0x183d5104c) [0x14fac9960 - Unity Child Domain]
#10 0x00000185a02a08 in (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr) {0x7fa4ae1f53c0} + 0x168 (0x185a028a0 0x185a02bea) [0x14fac9960 - Unity Child Domain]
#11 0x0000014f3d0285 in mono_jit_runtime_invoke
#12 0x0000014f56e28b in do_runtime_invoke
#13 0x0000014f56e1e5 in mono_runtime_invoke
#14 0x0000010df37df7 in scripting_method_invoke(ScriptingMethodPtr, ScriptingObjectPtr, ScriptingArguments&, ScriptingExceptionPtr*, bool)
#15 0x0000010df33416 in ScriptingInvocation::Invoke(ScriptingExceptionPtr*, bool)
#16 0x0000010df4ec61 in void InvokeMethod(SerializationCommandArguments const&, RuntimeSerializationCommandInfo&)
#17 0x0000010df01b26 in void TransferScriptingObject<StreamedBinaryWrite, true>(StreamedBinaryWrite&, ScriptingObjectPtr, ScriptingClassPtr, SerializationCache::smile:ata*&, ManagedReferencesRegistry*)
#18 0x0000010df00de8 in SerializableManagedRefBackupGenerator::ExtractBackupFromInstance(Object*, SerializableManagedRef&, BackupState&, TransferInstructionFlags)
#19 0x0000010deeafa6 in void SerializableManagedRefTransfer::BackupAndDeflateManagedReferences(Object*, SerializableManagedRef&, bool)
#20 0x0000010df9e5d2 in SerializableManagedRefsUtilities::BackupAndDeflateAll(DomainReloadingData&)
#21 0x0000010def0b4e in MonoManager::BeginReloadAssembly(DomainReloadingData&)
#22 0x0000010deef630 in MonoManager::ReloadAssembly()
#23 0x0000010eae2780 in ReloadAllUsedAssemblies()
#24 0x0000010ed4864e in RefreshInternalV2(AssetDatabase::UpdateAssetOptions, ScanFilter const&, InternalRefreshFlagsV2)
#25 0x0000010ed27ce4 in StopAssetImportingV2(AssetDatabase::UpdateAssetOptions, InternalRefreshFlagsV2, ScanFilter const*)
#26 0x0000010ed28337 in RefreshV2(AssetDatabase::UpdateAssetOptions)
#27 0x0000010ecb8d8e in AssetDatabase::Refresh(AssetDatabase::UpdateAssetOptions)
#28 0x0000010e793413 in Application::AutoRefresh()
#29 0x0000010fae9171 in -[EditorApplication applicationDidBecomeActive:]
#30 0x007fff207ea483 in CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER
#31 0x007fff20885ef9 in ___CFXRegistrationPost_block_invoke
#32 0x007fff20885e74 in _CFXRegistrationPost
#33 0x007fff207bb70e in _CFXNotificationPost
#34 0x007fff2152dbc8 in -[NSNotificationCenter postNotificationName:object:userInfo:]
#35 0x007fff231b5077 in -[NSApplication _handleActivatedEvent:]
#36 0x007fff231841c5 in -[NSApplication(NSEvent) sendEvent:]
#37 0x0000010fb06e1e in -[EditorApplicationPrincipalClass sendEvent:]
#38 0x007fff2345c531 in -[NSApplication _handleEvent:]
#39 0x007fff22fec62e in -[NSApplication run]
#40 0x007fff22fc080c in NSApplicationMain
#41 0x0000010fb07541 in EditorMain(int, char const**)
#42 0x0000010fb07769 in main
#43 0x007fff20717f3d in start

These are definitely not things you should do in OnBefore/OnAfterSerialize.

It’s a threaded process so you should not reach outside the object in question.

“Care needs to be taken whilst within these callbacks, as Unity’s serializer runs on a different thread to most of the Unity API. It is advisable to only process fields directly owned by the object, keeping the processing burden as low as possible.”

crap, i’ve missed that

so, where/how to handle this kind of stuff?
OnValidate is the same problem

Explain what it is you are trying to achieve please.

From your initial post it sounds like initialisation stuff? Are you able to use Awake/Start/OnEnable?

Otherwise you could try EditorApplication.delayCall, which happens on the main thread once inspectors have updated.

i’d like to handle two cases:

  • when component is created I’d like to do some auto linking (like find parent component and inject myself into it’s list)
  • when an object gets saved, I’d like to do so collection, i.e. find all components of certain type in children and store them in a serialized list

The first one you can do with the Reset() callback that gets invoked when you add a component.

Not sure about the second one. Personally this is the sort of thing I’d make editor buttons, etc, for.