[ru] Strange serialization error (solved)

Topics: Technical Support
Aug 12 at 1:44 PM
We use .net on mono and receive this error:

Unhandled Exception:
System.IndexOutOfRangeException: Array index is out of range.
at System.Runtime.Serialization.Formatters.Binary.BinaryCommon.GetTypeFromCode (Int32 code) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadType (System.IO.BinaryReader reader, TypeTag code, Boolean throwOnError) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadType (System.IO.BinaryReader reader, TypeTag code) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadBoxedPrimitiveTypeValue (System.IO.BinaryReader reader) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObject (BinaryElement element, System.IO.BinaryReader reader, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadNextObject (BinaryElement element, System.IO.BinaryReader reader) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectGraph (BinaryElement elem, System.IO.BinaryReader reader, Boolean readHeaders, System.Object& result, System.Runtime.Remoting.Messaging.Header[]& headers) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.NoCheckDeserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) [0x00000] in <filename unknown>:0
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) [0x00000] in <filename unknown>:0
at Zyan.Communication.Protocols.Tcp.DuplexChannel.Connection.ReceiveChannelInfo () [0x00000] in <filename unknown>:0
at Zyan.Communication.Protocols.Tcp.DuplexChannel.Connection..ctor (System.Net.Sockets.Socket socket, Zyan.Communication.Protocols.Tcp.DuplexChannel.TcpExChannel channel, Boolean keepAlive, UInt64 keepAliveTime, UInt64 KeepAliveInterval, Int16 maxRetries, Int32 retryDelay) [0x00000] in <filename unknown>:0
at Zyan.Communication.Protocols.Tcp.DuplexChannel.Connection.CreateConnection (System.Net.Sockets.Socket socket, Zyan.Communication.Protocols.Tcp.DuplexChannel.TcpExChannel channel, Boolean keepAlive, UInt64 keepAliveTime, UInt64 KeepAliveInterval, Int16 maxRetries, Int32 retryDelay) [0x00000] in <filename unknown>:0
at Zyan.Communication.Protocols.Tcp.DuplexChannel.Manager.listener_Accept (IAsyncResult ar) [0x00000] in <filename unknown>:0

Сталкивались ли вы с такой проблемой?
Проявляется крайне редко.
Coordinator
Aug 12 at 3:11 PM
Не сталкивался, честно говоря.

Это с обоих концов стоит моно или .NET общается с моно?
Попробуйте сохранить трафик в файл, поймать это сообщение и посмотреть, что это там такое.
Вообще похоже на баг в BinaryFormatter, хотя это и крайне маловероятно.
Как будто список type codes не совпадает...
Aug 13 at 7:26 AM
Edited Aug 13 at 7:27 AM
И сервер и клиент на моно.
На сервере выпадает такая ошибка и приложение закрывается. Так как выловить ошибку нельзя.
Можно конечно сохранить трафик в файлик, но сервер зачастую работает несколько недель с кучей транзакций, а потом падает. Большой файлик будет.
Причём как мы поняли, это происходит при входящем запросе.
Возможно это баг самого моно, например он зачастую дату не правильно сереализует +-3 часа.

Есть ли возможность избавится от бинарного сериализатора, и перейти на json.net или protobuf? Эти технологии на моно работают, проверенно временем.
Coordinator
Aug 13 at 1:01 PM
Edited Aug 13 at 1:04 PM
Json и Protobuf на моно работают, но они даже близко не соответствуют возможностям
BinaryFormatter. Ни один из них в инфраструктуру remoting не интегрируется, объекты MBR
сериализовать не умеет, интерфейс ISerializable не поддерживает (т. е. не будут работать
события, параметры типа Stream, delegate, LINQ expressions и так далее).
 
Причём как мы поняли, это происходит при входящем запросе.
 
Судя по вашему call stack — действительно, это происходит при установке соединения.
Проверьте, не было ли таких ошибок в других местах. Если нет — тогда можно поэкспериментировать
с объектом TcpExChannelData, сделать его сериализацию более переносимой.

Самый дешевый способ обойти эту ошибку — попробовать вместо TcpEx стандартный Tcp-канал.
Он не дуплексный, но не факт, что в вашем случае нужна именно дуплексная связь.
Дуплексный канал нужен, если клиенты спрятаны за NAT или файрволлом, и сервер не может
по своей инициативе с ними установить соединение. В общем, я бы на вашем месте попробовал :)
 
Возможно это баг самого моно, например он зачастую дату не правильно сереализует +-3 часа.
 
Не факт, что с датами это баг :)
Похоже на автоматическую коррекцию даты по часовому поясу компьютера.
Coordinator
Nov 22 at 8:33 PM
Edited Nov 22 at 8:46 PM
Перечитал дискуссию и вижу, что проморгал я здесь важный момент.

Ошибки сериализации/десериализации в Моно это отдельный вопрос, но в любом случае, ни при каких подобных ошибках сервер не должен падать. Я сделал тикет по этой теме: #2618. Как минимум, падение сервера необходимо устранить.

Кстати, насчет BinaryFormatter. Скачал я вчера последний tarball исходников Моно и смотрю, что они в конце концов просто выбросили свои исходники и используют MIT-лицензированный код Microsoft. Так что в распоследнем Моно такой ошибки десериализации встречаться больше не должно.
Coordinator
Nov 22 at 8:49 PM
Edited Nov 22 at 10:54 PM
Падение сервера пофиксил, в релизе 2.8 все должно быть хорошо.
Попробуйте обновиться, когда будет возможность!
Marked as answer by yallie on 11/22/2016 at 12:49 PM