-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Fix serialization verification problem with Akka.IO messages #4974
Changes from all commits
6e3dacb
b340a79
bed4022
f1b4440
cf23a2d
bbcb132
aae8b4a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,8 @@ class AckWithValue : Tcp.Event | |
|
||
public TcpIntegrationSpec(ITestOutputHelper output) | ||
: base($@"akka.loglevel = DEBUG | ||
akka.actor.serialize-creators = on | ||
akka.actor.serialize-messages = on | ||
akka.io.tcp.trace-logging = true | ||
akka.io.tcp.write-commands-queue-max-size = {InternalConnectionActorMaxQueueSize}", output: output) | ||
{ } | ||
|
@@ -190,7 +192,7 @@ public void The_TCP_transport_implementation_should_properly_support_connecting_ | |
var targetAddress = new DnsEndPoint("localhost", boundMsg.LocalAddress.AsInstanceOf<IPEndPoint>().Port); | ||
var clientHandler = CreateTestProbe(); | ||
Sys.Tcp().Tell(new Tcp.Connect(targetAddress), clientHandler); | ||
clientHandler.ExpectMsg<Tcp.Connected>(TimeSpan.FromMinutes(10)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A socket shouldn't take 10 minutes to connect |
||
clientHandler.ExpectMsg<Tcp.Connected>(TimeSpan.FromSeconds(3)); | ||
var clientEp = clientHandler.Sender; | ||
clientEp.Tell(new Tcp.Register(clientHandler)); | ||
serverHandler.ExpectMsg<Tcp.Connected>(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,12 +19,14 @@ namespace Akka.Tests.IO | |
public class TcpListenerSpec : AkkaSpec | ||
{ | ||
public TcpListenerSpec() | ||
: base(@"akka.io.tcp.register-timeout = 500ms | ||
: base(@" | ||
akka.actor.serialize-creators = on | ||
akka.actor.serialize-messages = on | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leaving this here so we can test similar problems in the future |
||
akka.io.tcp.register-timeout = 500ms | ||
akka.io.tcp.max-received-message-size = 1024 | ||
akka.io.tcp.direct-buffer-size = 512 | ||
akka.actor.serialize-creators = on | ||
akka.io.tcp.batch-accept-limit = 2 | ||
") | ||
akka.io.tcp.batch-accept-limit = 2") | ||
{ } | ||
|
||
[Fact] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,8 @@ public class UdpConnectedIntegrationSpec : AkkaSpec | |
|
||
public UdpConnectedIntegrationSpec(ITestOutputHelper output) | ||
: base(@" | ||
akka.actor.serialize-creators = on | ||
akka.actor.serialize-messages = on | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leaving this here so we can test similar problems in the future |
||
akka.io.udp-connected.nr-of-selectors = 1 | ||
akka.io.udp-connected.direct-buffer-pool-limit = 100 | ||
akka.io.udp-connected.direct-buffer-size = 1024 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,8 @@ public class UdpIntegrationSpec : AkkaSpec | |
|
||
public UdpIntegrationSpec(ITestOutputHelper output) | ||
: base(@" | ||
akka.actor.serialize-creators = on | ||
akka.actor.serialize-messages = on | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leaving this here so we can test similar problems in the future |
||
akka.io.udp.max-channels = unlimited | ||
akka.io.udp.nr-of-selectors = 1 | ||
akka.io.udp.direct-buffer-pool-limit = 100 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,17 +13,21 @@ | |
using Akka.IO; | ||
using Akka.TestKit; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
using UdpListener = Akka.IO.UdpListener; | ||
|
||
namespace Akka.Tests.IO | ||
{ | ||
public class UdpListenerSpec : AkkaSpec | ||
{ | ||
public UdpListenerSpec() | ||
: base(@"akka.io.udp.max-channels = unlimited | ||
public UdpListenerSpec(ITestOutputHelper output) | ||
: base(@" | ||
akka.actor.serialize-creators = on | ||
akka.actor.serialize-messages = on | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leaving this here so we can test similar problems in the future |
||
akka.io.udp.max-channels = unlimited | ||
akka.io.udp.nr-of-selectors = 1 | ||
akka.io.udp.direct-buffer-pool-limit = 100 | ||
akka.io.udp.direct-buffer-size = 1024") | ||
akka.io.udp.direct-buffer-size = 1024", output) | ||
{ } | ||
|
||
[Fact] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,8 +10,10 @@ | |
using System.Collections.Immutable; | ||
using System.Text; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.Serialization; | ||
using System.Threading; | ||
using Akka.Actor.Internal; | ||
using Akka.Dispatch.SysMsg; | ||
using Akka.Serialization; | ||
using Akka.Util; | ||
using Akka.Util.Internal; | ||
|
@@ -452,6 +454,7 @@ private IInternalActorRef MakeChild(Props props, string name, bool async, bool s | |
if (_systemImpl.Settings.SerializeAllCreators && !systemService && !(props.Deploy.Scope is LocalScope)) | ||
{ | ||
var oldInfo = Serialization.Serialization.CurrentTransportInformation; | ||
object propArgument = null; | ||
try | ||
{ | ||
if (oldInfo == null) | ||
|
@@ -465,17 +468,24 @@ private IInternalActorRef MakeChild(Props props, string name, bool async, bool s | |
{ | ||
if (argument != null && !(argument is INoSerializationVerificationNeeded)) | ||
{ | ||
propArgument = argument; | ||
var serializer = ser.FindSerializerFor(argument); | ||
var bytes = serializer.ToBinary(argument); | ||
var ms = Serialization.Serialization.ManifestFor(serializer, argument); | ||
if(ser.Deserialize(bytes, serializer.Identifier, ms) == null) | ||
if (ser.Deserialize(bytes, serializer.Identifier, ms) == null) | ||
throw new ArgumentException( | ||
$"Pre-creation serialization check failed at [${_self.Path}/{name}]", | ||
nameof(name)); | ||
$"Pre-creation serialization check failed at [${_self.Path}/{name}]", | ||
nameof(name)); | ||
} | ||
} | ||
} | ||
} | ||
catch (Exception e) | ||
{ | ||
throw new SerializationException( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Catch and re-throw to add a more meaningful exception message to the error |
||
$"Failed to serialize and deserialize actor props argument of type {propArgument?.GetType()} for actor type [{props.Type}].", | ||
e); | ||
} | ||
finally | ||
{ | ||
Serialization.Serialization.CurrentTransportInformation = oldInfo; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,9 +71,9 @@ private IEnumerable<SocketAsyncEventArgs> Accept(int limit) | |
{ | ||
var self = Self; | ||
var saea = new SocketAsyncEventArgs(); | ||
saea.Completed += (s, e) => self.Tell(e); | ||
saea.Completed += (s, e) => self.Tell(new SocketEvent(e)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrap naked SocketAsyncEventArgs in a struct There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
if (!_socket.AcceptAsync(saea)) | ||
Self.Tell(saea); | ||
Self.Tell(new SocketEvent(saea)); | ||
yield return saea; | ||
} | ||
} | ||
|
@@ -85,34 +85,34 @@ protected override SupervisorStrategy SupervisorStrategy() | |
|
||
protected override bool Receive(object message) | ||
{ | ||
if (message is SocketAsyncEventArgs) | ||
switch (message) | ||
{ | ||
var saea = message as SocketAsyncEventArgs; | ||
if (saea.SocketError == SocketError.Success) | ||
Context.ActorOf(Props.Create<TcpIncomingConnection>(_tcp, saea.AcceptSocket, _bind.Handler, _bind.Options, _bind.PullMode).WithDeploy(Deploy.Local)); | ||
saea.AcceptSocket = null; | ||
case SocketEvent evt: | ||
var saea = evt.Args; | ||
if (saea.SocketError == SocketError.Success) | ||
Context.ActorOf(Props.Create<TcpIncomingConnection>(_tcp, saea.AcceptSocket, _bind.Handler, _bind.Options, _bind.PullMode).WithDeploy(Deploy.Local)); | ||
saea.AcceptSocket = null; | ||
|
||
if (!_socket.AcceptAsync(saea)) | ||
Self.Tell(saea); | ||
return true; | ||
} | ||
var resumeAccepting = message as Tcp.ResumeAccepting; | ||
if (resumeAccepting != null) | ||
{ | ||
_acceptLimit = resumeAccepting.BatchSize; | ||
_saeas = Accept(_acceptLimit).ToArray(); | ||
return true; | ||
} | ||
if (message is Tcp.Unbind) | ||
{ | ||
_log.Debug("Unbinding endpoint {0}", _bind.LocalAddress); | ||
_socket.Dispose(); | ||
Sender.Tell(Tcp.Unbound.Instance); | ||
_log.Debug("Unbound endpoint {0}, stopping listener", _bind.LocalAddress); | ||
Context.Stop(Self); | ||
return true; | ||
if (!_socket.AcceptAsync(saea)) | ||
Self.Tell(new SocketEvent(saea)); | ||
return true; | ||
|
||
case Tcp.ResumeAccepting resumeAccepting: | ||
_acceptLimit = resumeAccepting.BatchSize; | ||
_saeas = Accept(_acceptLimit).ToArray(); | ||
return true; | ||
|
||
case Tcp.Unbind _: | ||
_log.Debug("Unbinding endpoint {0}", _bind.LocalAddress); | ||
_socket.Dispose(); | ||
Sender.Tell(Tcp.Unbound.Instance); | ||
_log.Debug("Unbound endpoint {0}, stopping listener", _bind.LocalAddress); | ||
Context.Stop(Self); | ||
return true; | ||
|
||
default: | ||
return false; | ||
} | ||
return false; | ||
} | ||
|
||
/// <summary> | ||
|
@@ -130,5 +130,15 @@ protected override void PostStop() | |
_log.Debug("Error closing ServerSocketChannel: {0}", e); | ||
} | ||
} | ||
|
||
private readonly struct SocketEvent : INoSerializationVerificationNeeded | ||
{ | ||
public readonly SocketAsyncEventArgs Args; | ||
|
||
public SocketEvent(SocketAsyncEventArgs args) | ||
{ | ||
Args = args; | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving this here so we can test similar problems in the future