Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to serialize session because SerializationFieldInfo is not marked as serializable #1964

Closed
cremor opened this issue Jan 10, 2019 · 9 comments

Comments

@cremor
Copy link
Contributor

cremor commented Jan 10, 2019

I can't update an application from NHibernate 5.1.4 to 5.2.2 (I've also tested 5.2.0). If I update and try to serialize an ISession the following exception is thrown in some cases:

System.Runtime.Serialization.SerializationException: Type 'System.Runtime.Serialization.SerializationFieldInfo' in Assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
   at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
   at System.Runtime.Serialization.FormatterServices.<>c__DisplayClass9_0.<GetSerializableMembers>b__0(MemberHolder _)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
   at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
   at <my code calling binaryFormatter.Serialize(memoryStream, session)>

Since SerializationFieldInfo is internal in mscorlib neither my code nor NHibernate can reference it directly. But something must have changed between NHibernate 5.1 and 5.2 that causes an ISession to indirectly contain a SerializationFieldInfo somewhere.

I'm not sure why some sessions cause this issue for me and others don't. I haven't been able to find a specific entity that causes it yet.

My application targets Framework 4.7.1 and I'm currently on the 4.7.2 runtime (Windows 10 1709).

@fredericDelaporte
Copy link
Member

NHibernate has many session serialization tests, and they do not fail. Can you give more information on how to reproduce this?

@cremor
Copy link
Contributor Author

cremor commented Jan 10, 2019

Not yet, but I'll continue to investigate how to reproduce it. Although it is 100% reproduceable on my failing tests, only very few tests are affected for my application too (less than 10% of those that use NHibernate).

I assume only very specific entity mappings trigger the bug, so I'll try to find out which ones tomorrow.

@cremor
Copy link
Contributor Author

cremor commented Jan 11, 2019

I think I found the problem. Although I don't have a unit test for NHibernate yet or even fully understand it, that's what I found by debugging the .NET Framework serialization code:

Objects of the type FieldInterceptorObjectReference have a field named "proxy$additionalMembers" of type MemberInfo[]. This array contains the SerializationFieldInfo objects that can't be serialized. The fields that are wrapped by the SerializationFieldInfo objects are those of base classes of entities (see background information below). The FieldInterceptorObjectReference objects itself are referenced by <entityType>ProxyForFieldInterceptor objects. Since both of those FieldInterceptor classes didn't exist yet in 5.1 it makes sense that that version didn't fail.

Some background information:

  1. The only place that SerializationFieldInfo is instantiated is the same method that also throws the exception: FormatterServices.InternalGetSerializableMembers
  2. That line is called for all fields that are in parent types of entities, e.g. for Entity.Id or Entity.Version properties (or to be exact - for their backing fields) in a Entity base class. For one of my unit tests which fails with 5.2.2, the line seems to be called the same amout of times in 5.1.4 and 5.2.2. At least the call count is the same for the successful run of 5.1.4 and the run of 5.2.2 until the exception is thrown. The fields that are wrapped in that object are also the same, just the order is very slightly different (6 differences in 316 objects). So it seems like the creation of the SerializationFieldInfo objects is not the problem, just that they are referenced somewhere.
  3. I printed out obj and objectInfo.obj that are enqueued for serialization in ObjectWriter.Schedule. The difference between 5.1.4 and 5.2.2 is that 5.2.2 tries to serialize arrays of MemberInfo objects and those arrays contain the SerializationFieldInfo objects. I couldn't find any MemberInfo array serialization being done with 5.1.4.

@bahusoid
Copy link
Member

bahusoid commented Jan 11, 2019

So it's related to entities with lazy properties. And the issue can easily be reproduced on existing test

public void SessionSerializationWithLazyProperty()

If LazyTextEntity is modified in the following way (added base class with unmapped property) :

[Serializable]
public class LazyTextEntity : BaseTextEntity
{
	public virtual Guid Id { get; set; }
	public virtual string Name { get; set; }
	public virtual string Text { get; set; }
}

[Serializable]
public class BaseTextEntity
{
	public virtual int Test { get; set; }
}

@cremor
Copy link
Contributor Author

cremor commented Jan 11, 2019

So it's related to entities with lazy properties.

I'm not in front of my code right now, but I'm 99% sure that I don't have any lazy properties. So there has to be another case where these classes are used.

@hazzik
Copy link
Member

hazzik commented Jan 12, 2019

The following kind of contradicts each other:

Objects of the type FieldInterceptorObjectReference

but I'm 99% sure that I don't have any lazy properties.

@hazzik
Copy link
Member

hazzik commented Jan 12, 2019

I have seen this error in regarding to arrays (and particularly arrays of MemberInfo). This is the reason why we have SerializationHelper.AddValueArray and SerializationHelper.GetValueArray.

@hazzik hazzik added this to the 5.2.3 milestone Jan 12, 2019
hazzik added a commit to hazzik/nhibernate-core that referenced this issue Jan 12, 2019
maca88 added a commit to maca88/nhibernate-core that referenced this issue Jan 13, 2019
@cremor
Copy link
Contributor Author

cremor commented Jan 13, 2019

The following kind of contradicts each other:

I'll check that tomorrow.

@fredericDelaporte
Copy link
Member

but I'm 99% sure that I don't have any lazy properties.

It may also be associations mapped with lazy="no-proxy".

@hazzik hazzik changed the title 5.2 regression: Unable to serialize session because SerializationFieldInfo is not marked as serializable Unable to serialize session because SerializationFieldInfo is not marked as serializable Jan 13, 2019
hazzik added a commit to hazzik/nhibernate-core that referenced this issue Jan 13, 2019
hazzik added a commit to hazzik/nhibernate-core that referenced this issue Jan 13, 2019
hazzik added a commit to hazzik/nhibernate-core that referenced this issue Jan 13, 2019
The fields should not change between serialization and deserialization.

Fixes nhibernate#1964
fredericDelaporte added a commit that referenced this issue Jan 13, 2019
Fix session no more serializable with entities having a field interceptor
Fix #1964
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants