Using UnixSignal in Mono throws System.ArgumentException - c#

I have a console app running .Net 4.6.1 on mono in a Docker Container and it runs fine. When developing the app further I'm looking into responding to unix signals using the Nuget-package Mono.Posix.
According to the Mono documentation it is recommended running the UnixSignal handling in a separate thread.
So I'm trying to do this like the code below:
public void Run()
{
var signalHandler = new Thread(new ThreadStart(ListenToSignal));
signalHandler.Start();
}
private void ListenToSignal()
{
var signals = new List<UnixSignal>() {
new UnixSignal (Mono.Unix.Native.Signum.SIGHUP),
new UnixSignal (Mono.Unix.Native.Signum.SIGINT),
new UnixSignal (Mono.Unix.Native.Signum.SIGQUIT),
new UnixSignal (Mono.Unix.Native.Signum.SIGTERM)
};
int index = UnixSignal.WaitAny(signals.ToArray());
var signal = signals[index].Signum;
Console.WriteLine($"Terminate signal was called: {signal}");
}
When starting the application it throws a ArgrumentException:
Unhandled Exception: System.ArgumentException: Unable to handle signal
Parameter name: signum at Mono.Unix.UnixSignal..ctor (Signum signum)
<0x40433de0 + 0x00097> in :0 at (wrapper
remoting-invoke-with-check) Mono.Unix.UnixSignal:.ctor
(Mono.Unix.Native.Signum) at
MangoFareScrapingGenericClient.Scraping.ListenToSignal () <0x404339e0
+ 0x00117> in :0 at System.Threading.ThreadHelper.ThreadStart_Context (System.Object
state) <0x7f20f10b1010 + 0x00099> in :0 at
System.Threading.ExecutionContext.RunInternal
(System.Threading.ExecutionContext executionContext,
System.Threading.ContextCallback callback, System.Object state,
Boolean preserveSyncCtx) <0x7f20f10af850 + 0x0016e> in :0 at System.Threading.ExecutionContext.Run
(System.Threading.ExecutionContext executionContext,
System.Threading.ContextCallback callback, System.Object state,
Boolean preserveSyncCtx) <0x7f20f10af820 + 0x00020> in :0 at System.Threading.ExecutionContext.Run
(System.Threading.ExecutionContext executionContext,
System.Threading.ContextCallback callback, System.Object state)
<0x7f20f10af770 + 0x00059> in :0 at
System.Threading.ThreadHelper.ThreadStart () <0x7f20f10b11d0 +
0x0002e> in :0
If I look on Github for the specific code it looks like signal_info is a IntPtr.Zero which throws the exception.
public UnixSignal (Signum signum)
{
this.signum = NativeConvert.FromSignum (signum);
this.signal_info = install (this.signum);
if (this.signal_info == IntPtr.Zero) {
throw new ArgumentException ("Unable to handle signal", "signum");
}
}

SIGTERM and SIGINT support was added to Docker in ~2013 (I remember the pull-request because I needed that support in a deployment)
So I'm assuming either SIGQUIT or SIGHUP is failing to be installed.
But, since you did not say which signal is returning a IntPtr.Zero and thus throwing the exception, I would try installing each signal on its own to find the one that is not supported in your Ubuntu Docker environment.
At that point, you can test that signal under a straight C program to determine if it runs ok as it might be a problem in the Mono runtime running under Docker.
Plus you can try/catch your UnixSignal.WaitAny and gracefully degrade your signal processing and write a log message about the offending signal.

Related

SignalR HubConnection StopAsync throws ObjectDisposedException

We have a WPF client that connects with SignalR to one of our servers. When closing the WPF client we also close the SignalR HubConnection:
public HubConnection Connection => _connection ??= GetConnection();
private HubConnection GetConnection()
{
var host = ConfigurationManager.AppSettings["SignalRHost"];
var connection = new HubConnectionBuilder()
.WithUrl(host)
.Build();
connection.Closed += ConnectionOnClosed;
return connection;
}
private async Task ConnectionOnClosed(Exception exception)
{
// The connection is disconnected
if (_disconnecting)
{
// The disconnect was requested by the client
Connection.Closed -= ConnectionOnClosed;
Logger.Information("The connection to SignalR hub was closed.");
}
else
{
await StartAsync();
}
}
public async Task Disconnect()
{
if (_disconnecting) return;
try
{
_disconnecting = true;
await _connection.StopAsync();
}
catch (Exception e)
{
Logger.Error(e, "Error in closing connection");
}
finally
{
await _connection.DisposeAsync();
_connection = null;
}
}
Calling CloseAsync results in two ObjectDisposedExceptions. I only have a partial stacktrace (that seems to be another problem in my VS):
System.dll!System.Net.Sockets.NetworkStream.InternalSocket.get() Line 136
System.dll!System.Net.PooledStream.CancelPendingIoAndCloseIfSafe(bool closeWithTimeout, int timeout) Line 596
System.dll!System.Net.PooledStream.Close(int timeout) Line 682
System.dll!System.Net.Connection.AbortOrDisassociate(System.Net.HttpWebRequest request, System.Net.WebException webException) Line 2859
System.dll!System.Net.HttpWebRequest.Abort(System.Exception exception, int abortState) Line 3173
System.dll!System.Net.HttpWebRequest.Abort() Line 3133
System.dll!System.Net.WebSockets.ClientWebSocket.AbortRequest(object obj) Line 366
mscorlib.dll!System.Threading.CancellationCallbackInfo.ExecutionContextCallback(object obj) Line 1031
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 980
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 928
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Line 917
mscorlib.dll!System.Threading.CancellationCallbackInfo.ExecuteCallback() Line 1021
mscorlib.dll!System.Threading.CancellationTokenSource.CancellationCallbackCoreWork(System.Threading.CancellationCallbackCoreWorkArguments args) Line 863
mscorlib.dll!System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(bool throwOnFirstException) Line 808
mscorlib.dll!System.Threading.CancellationTokenSource.NotifyCancellation(bool throwOnFirstException) Line 743
System.dll!System.Net.WebSockets.ClientWebSocket.Dispose() Line 377
System.dll!System.Net.WebSockets.ClientWebSocket.Abort() Line 360
Microsoft.AspNetCore.Http.Connections.Client.dll!Microsoft.AspNetCore.Http.Connections.Client.Internal.WebSocketsTransport.ProcessSocketAsync(System.Net.WebSockets.WebSocket socket) Line 220
And the next:
> System.dll!System.Net.Sockets.NetworkStream.InternalSocket.get() Line 136 C#
System.dll!System.Net.PooledStream.CancelPendingIoAndCloseIfSafe(bool closeWithTimeout, int timeout) Line 596 C#
System.dll!System.Net.PooledStream.Close(int timeout) Line 682 C#
System.dll!System.Net.Connection.AbortSocket(bool isAbortState) Line 2901 C#
System.dll!System.Net.ConnectStream.CloseInternal(bool internalCall, bool aborting) Line 2707 C#
System.dll!System.Net.ConnectStream.System.Net.ICloseEx.CloseEx(System.Net.CloseExState closeState) Line 2426 C#
System.dll!System.Net.HttpWebResponse.Abort() Line 479 C#
System.dll!System.Net.HttpWebRequest.SetResponse(System.Exception E) Line 3968 C#
System.dll!System.Net.HttpWebRequest.SetAndOrProcessResponse(object responseOrException) Line 3661 C#
System.dll!System.Net.ConnectionReturnResult.SetResponses(System.Net.ConnectionReturnResult returnResult) Line 205 C#
System.dll!System.Net.Connection.AbortOrDisassociate(System.Net.HttpWebRequest request, System.Net.WebException webException) Line 2873 C#
System.dll!System.Net.HttpWebRequest.Abort(System.Exception exception, int abortState) Line 3173 C#
System.dll!System.Net.HttpWebRequest.Abort() Line 3133 C#
System.Net.Http.dll!System.Net.Http.HttpClientHandler.OnCancel(object state) Line 1210 C#
mscorlib.dll!System.Threading.CancellationCallbackInfo.ExecutionContextCallback(object obj) Line 1031 C#
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 980 C#
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 928 C#
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Line 917 C#
mscorlib.dll!System.Threading.CancellationCallbackInfo.ExecuteCallback() Line 1021 C#
mscorlib.dll!System.Threading.CancellationTokenSource.CancellationCallbackCoreWork(System.Threading.CancellationCallbackCoreWorkArguments args) Line 863 C#
mscorlib.dll!System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(bool throwOnFirstException) Line 808 C#
mscorlib.dll!System.Threading.CancellationTokenSource.NotifyCancellation(bool throwOnFirstException) Line 743 C#
mscorlib.dll!System.Threading.CancellationTokenSource.LinkedTokenCancelDelegate(object source) Line 91 C#
mscorlib.dll!System.Threading.CancellationCallbackInfo.ExecutionContextCallback(object obj) Line 1031 C#
mscorlib.dll!System.Threading.CancellationCallbackInfo.ExecuteCallback() Line 1021 C#
mscorlib.dll!System.Threading.CancellationTokenSource.CancellationCallbackCoreWork(System.Threading.CancellationCallbackCoreWorkArguments args) Line 863 C#
mscorlib.dll!System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(bool throwOnFirstException) Line 808 C#
mscorlib.dll!System.Threading.CancellationTokenSource.NotifyCancellation(bool throwOnFirstException) Line 743 C#
mscorlib.dll!System.Threading.CancellationTokenSource.TimerCallbackLogic(object obj) Line 534 C#
mscorlib.dll!System.Threading.TimerQueueTimer.CallCallbackInContext(object state) Line 730 C#
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 980 C#
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 928 C#
mscorlib.dll!System.Threading.TimerQueueTimer.CallCallback() Line 713 C#
mscorlib.dll!System.Threading.TimerQueueTimer.Fire() Line 670 C#
mscorlib.dll!System.Threading.TimerQueue.FireQueuedTimerCompletion(object state) Line 444 C#
mscorlib.dll!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() Line 1252 C#
mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() Line 820 C#
mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Line 1161 C#
The server is running in Visual Studio at http://localhost:5008/tubahub. When running the server in IIS on the same machine we also get a SocketException when calling StopAsync due to a timeout. Perhaps that is related.

Game-Server running on local machine but not on ubuntu server

My Server (System.Net) is working on my local mashine (win10), but not on the ubuntu server, i get this error:
Unhandled exception. System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'size')
at System.Net.Sockets.NetworkStream.BeginRead(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at Server.Client.Start() in C:\Users\xxxx\source\repos\Server\Server\Client.cs:line 28
at Server.ClientManager.CreateNewConnection(TcpClient tempClient) in C:\Users\xxxx\source\repos\Server\Server\ClientManager.cs:line 19
at Server.Server.OnClientConnect(IAsyncResult result) in C:\Users\xxxx\source\repos\Server\Server\Server.cs:line 61
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.ContextAwareResult.CompleteCallback()
at System.Net.ContextAwareResult.<>c.<Complete>b__15_0(Object s)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.ContextAwareResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionCallback(Int32 numBytes, SocketError errorCode)
at System.Net.Sockets.AcceptOverlappedAsyncResult.CompletionCallback(IntPtr acceptedFileDescriptor, Byte[] socketAddress, Int32 socketAddressLen, SocketError errorCode)
at System.Net.Sockets.SocketAsyncContext.AcceptOperation.InvokeCallback(Boolean allowPooling)
at System.Net.Sockets.SocketAsyncContext.OperationQueue`1.ProcessAsyncOperation(TOperation op)
at System.Net.Sockets.SocketAsyncContext.ReadOperation.System.Threading.IThreadPoolWorkItem.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
Aborted (core dumped)
this is the code thats causing the error (its working on my local):
socket.SendBufferSize = 4096;
socket.ReceiveBufferSize = 4096;
stream = socket.GetStream();
recBuffer = new byte[4096];
stream.BeginRead(recBuffer, 0, socket.ReceiveBufferSize, OnReceiveData, null);
Console.WriteLine($"Connection from {socket.Client.RemoteEndPoint.ToString()}");
when i listen with netcat to the port im using (55555) and connect in the game, the connection works, so i think the port/firewall is fine.
i tried exporting it as a linux build, and as a windows build, which i executed via wine, both didn't work.
this is how i published it:
publish

How can I use rebus with simpleinjector

In my company we are using SimpleInjector as our IoC framework and are now looking at using Rebus as a wrapper for sending messages via RabbitMq. I am looking for help in creating a working example. I have tried the following code:
using Rebus.Activation;
using Rebus.Config;
using Rebus.Handlers;
using Rebus.Pipeline;
using Rebus.RabbitMq;
using Rebus.SimpleInjector;
using SimpleInjector;
using System;
using System.Threading.Tasks;
namespace SearchType.ProjectionA
{
class Program
{
static void Main(string[] args)
{
var container = new Container();
container.Register<IContainerAdapter, SimpleInjectorContainerAdapter>();
container.Register<IHandleMessages<string>, Handler>();
var adapter = container.GetInstance<IContainerAdapter>();
var bus = Configure.With(adapter)
.Logging(l => l.ColoredConsole())
.Transport(t => t.UseRabbitMq("amqp://localhost", "simpleinjector_consumer"))
.Start();
bus.Subscribe<string>().Wait();
Console.WriteLine("Projection A listening - press ENTER to quit");
Console.ReadLine();
}
}
public class Handler : IHandleMessages<string>
{
public Task Handle(string message)
{
return Task.Run(() =>
{
Console.WriteLine(string.Format("{0} - {1}", MessageContext.Current.Message.Headers["rbs2-corr-id"], message));
});
}
}
}
When i try and run this console application I am getting the following error:
System.InvalidOperationException was unhandled
HResult=-2146233079
Message=The container can't be changed after the first call to GetInstance, GetAllInstances and Verify. The following stack trace describes the location where the container was locked:
at SearchType.ProjectionA.Program.Main(String[] args) in C:\HRG\TravTech\Springboard\SearchType\SearchType.ProjectionA\Program.cs:line 34
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
Source=SimpleInjector
StackTrace:
at SimpleInjector.Container.ThrowWhenContainerIsLocked()
at SimpleInjector.Container.AddRegistration(Type serviceType, Registration registration)
at SimpleInjector.Container.RegisterSingleton[TService](TService instance)
at Rebus.SimpleInjector.SimpleInjectorContainerAdapter.SetBus(IBus bus)
at Rebus.Config.RebusConfigurer.Start()
at SearchType.ProjectionA.Program.Main(String[] args) in C:\HRG\TravTech\Springboard\SearchType\SearchType.ProjectionA\Program.cs:line 36
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Does anyone know what I can do to fix this? I don't want to have to declare all the dependencies myself.
Edit: thank you Steven for your reply. I have changed the code according to your answer and am now getting a different error.
System.InvalidOperationException was unhandled
HResult=-2146233079
Message=The configuration is invalid. Creating the instance for type IMessageContext failed. The registered delegate for type IMessageContext threw an exception. Attempted to inject the current message context from MessageContext.Current, but it was null! Did you attempt to resolve IMessageContext from outside of a Rebus message handler?
Source=SimpleInjector
StackTrace:
at SimpleInjector.InstanceProducer.VerifyInstanceCreation()
at SimpleInjector.Container.VerifyInstanceCreation(InstanceProducer[] producersToVerify)
at SimpleInjector.Container.VerifyThatAllRootObjectsCanBeCreated()
at SimpleInjector.Container.VerifyInternal(Boolean suppressLifestyleMismatchVerification)
at SimpleInjector.Container.Verify()
at SearchType.ProjectionA.Program.Main(String[] args) in C:\HRG\TravTech\Springboard\SearchType\SearchType.ProjectionA\Program.cs:line 27
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
HResult=-2146233088
Message=The registered delegate for type IMessageContext threw an exception. Attempted to inject the current message context from MessageContext.Current, but it was null! Did you attempt to resolve IMessageContext from outside of a Rebus message handler?
Source=SimpleInjector
StackTrace:
at SimpleInjector.InstanceProducer.GetInstance()
at SimpleInjector.InstanceProducer.VerifyInstanceCreation()
InnerException:
HResult=-2146233079
Message=Attempted to inject the current message context from MessageContext.Current, but it was null! Did you attempt to resolve IMessageContext from outside of a Rebus message handler?
Source=Rebus.SimpleInjector
StackTrace:
at Rebus.SimpleInjector.SimpleInjectorContainerAdapter.<SetBus>b__7()
at lambda_method(Closure )
at SimpleInjector.InstanceProducer.BuildAndReplaceInstanceCreatorAndCreateFirstInstance()
at SimpleInjector.InstanceProducer.GetInstance()
InnerException:
The error indicates that IMessageContext can only be instantiated inside a message handler. Is there a way to ignore certain errors?
I think the exception is clear; Simple Injector prevents registration after you already resolved. Reasons for doing this are described here.
The solution is to manually create the SimpleInjectorContainerAdapter and prevent relying on the container's auto-wiring capability for the adapter:
var container = new Container();
IContainerAdapter adapter = new SimpleInjectorContainerAdapter(container);
container.Register<IHandleMessages<string>, Handler>();
var bus = Configure.With(adapter)
.Logging(l => l.ColoredConsole())
.Transport(t => t.UseRabbitMq("amqp://localhost", "simpleinjector_consumer"))
.Start();
container.Verify();

WaitHandleCannotBeOpenedException on Azure web role start with Task.Wait()

The following (web) role entry point, after returning, causes the below exception to be thrown.
public class WebRole : RoleEntryPoint
{
public override bool OnStart()
{
Task.Run(() =>
{
// Anything can be here, but the lamdbda can be empty too...
}).Wait();
return true;
}
}
The exception:
A first chance exception of type
'System.Threading.WaitHandleCannotBeOpenedException' occurred in
mscorlib.dll
Additional information: No handle of the given name exists.
As apparent this is thrown from the framework. The exception appears to be harmless, I haven't experienced any issues.
Still I'm curious, why this happens? Is there a way to run async code in the role start method not causing such exceptions?
Edit:
This is the exception's call stack:
> mscorlib.dll!System.Threading.EventWaitHandle.OpenExisting(string name, System.Security.AccessControl.EventWaitHandleRights rights) Unknown
Microsoft.WindowsAzure.ServiceRuntime.dll!Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.StartRoleInternal() Unknown
Microsoft.WindowsAzure.ServiceRuntime.dll!Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.StartRole() Unknown
Microsoft.WindowsAzure.ServiceRuntime.dll!Microsoft.WindowsAzure.ServiceRuntime.Implementation.Loader.RoleRuntimeBridge.StartRole.AnonymousMethod__2() Unknown
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() Unknown
[Native to Managed Transition]
Edit 2:
This is the Azure runtime source in question:
private void StartRoleInternal()
{
string environmentVariable = Environment.GetEnvironmentVariable("RdRoleId");
string name = RoleEnvironment.NormalizeEventName("Global\\started_{0}", environmentVariable);
try
{
using (EventWaitHandle eventWaitHandle = EventWaitHandle.OpenExisting(name, EventWaitHandleRights.Modify))
{
eventWaitHandle.Set();
}
}
catch (WaitHandleCannotBeOpenedException)
{
}
RoleEnvironment.TraceSource.TraceEvent(TraceEventType.Information, 203, "Role entrypoint . CALLING Run(): " + this.role);
SystemEvents.LogEventToSystemEvents("Windows Azure Runtime 2.3.0.0", RuntimeEventType.OnRoleRunBegin, "Role is running: OnRun(): " + this.role);
this.role.Run();
RoleEnvironment.TraceSource.TraceEvent(TraceEventType.Warning, 204, "Role entrypoint . COMPLETED Run() ==> ROLE RECYCLING INITIATED: " + this.role);
SystemEvents.LogEventToSystemEvents("Windows Azure Runtime 2.3.0.0", RuntimeEventType.OnRoleRunEnd, "Role will recyle: OnRun(): " + this.role);
RoleEnvironment.RequestRecycle();
}

Setting HttpClient to a too short timeout crashes process

I've noticed that when I'm using System.Net.HttpClient with a short timeout, it may sometimes crash the process, even when it is wrapped in a try-catch block. Here's a short program to reproduce this.
public static void Main(string[] args)
{
var tasks = new List<Task>();
for (int i = 0; i < 1000; i++)
{
tasks.Add(MakeHttpClientRequest());
}
Task.WaitAll(tasks.ToArray());
}
private async static Task MakeHttpClientRequest()
{
var httpClient = new HttpClient { Timeout = TimeSpan.FromMilliseconds(1) };
var request = "whatever";
try
{
HttpResponseMessage result =
await httpClient.PostAsync("http://www.flickr.com/services/rest/?method=flickr.test.echo&format=json&api_key=766c0ac7802d55314fa980727f747710",
new StringContent(request));
await result.Content.ReadAsStringAsync();
}
catch (Exception x)
{
Console.WriteLine("Error occurred but it is swallowed: " + x);
}
}
Running this will crash the process with the following exception:
Unhandled Exception: System.AggregateException: One or more errors occurred. ---> System.Net.WebException: The request was canceled
at System.Net.ServicePointManager.FindServicePoint(Uri address, IWebProxy proxy, ProxyChain& chain, HttpAbortDelegate& abortDelegate, Int32& abortState)
at System.Net.HttpWebRequest.FindServicePoint(Boolean forceFind)
at System.Net.HttpWebRequest.get_ServicePoint()
at System.Net.AuthenticationState.PrepareState(HttpWebRequest httpWebRequest)
at System.Net.AuthenticationState.ClearSession(HttpWebRequest httpWebRequest)
at System.Net.HttpWebRequest.ClearAuthenticatedConnectionResources()
at System.Net.HttpWebRequest.Abort(Exception exception, Int32 abortState)
at System.Net.HttpWebRequest.Abort()
at System.Net.Http.HttpClientHandler.OnCancel(Object state)
at System.Threading.CancellationCallbackInfo.ExecutionContextCallback(Object obj)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.CancellationCallbackInfo.ExecuteCallback()
at System.Threading.CancellationTokenSource.CancellationCallbackCoreWork(CancellationCallbackCoreWorkArguments args)
at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
--- End of inner exception stack trace ---
at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
at System.Threading.CancellationTokenSource.NotifyCancellation(Boolean throwOnFirstException)
at System.Threading.CancellationTokenSource.TimerCallbackLogic(Object obj)
at System.Threading.TimerQueueTimer.CallCallbackInContext(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.TimerQueueTimer.CallCallback()
at System.Threading.TimerQueueTimer.Fire()
at System.Threading.TimerQueue.FireNextTimers()
at System.Threading.TimerQueue.AppDomainTimerCallback()
Digging in a little, it seems that when HttpClient aborts the request before a relevant ServicePoint is created, HttpWebRequest attempts to create the ServicePoint, via ServicePointManager.FindServicePoint, which throws a RequestCanceled. Since this exception is thrown in the thread that attempts to cancel the request, it is not caught, and the process dies.
Am I missing something? Have you run into this issue?
HttpWebRequest.Abort() is throwing an exception on a background/timer thread. This has nothing to do with HttpClient's Task management.
The exception from HttpWebRequest.Abort() should be fixed in .NET 4.5 GDR1.
http://support.microsoft.com/kb/2750149
http://support.microsoft.com/kb/2750147
Looks like it's some kind of bug in how the async handler for HttpClient is managing the tasks. I was able to launch the items in parallel, but run them synchronously and it works. I'm not sure if you want to just prevent the unhandled error or not. This ran parallel tasks, but they aren't async really since I turned it off. On my computer I would always get to 5 rounds and it would crash. Even if i set it to timeout after a second, it's like the crashes in the threads would still blow up if they were async.
I think it's a bug, I can't imagine this is intended behavior.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
namespace TestCrash
{
class Program
{
static void Main(string[] args)
{
try
{
Parallel.ForEach(Enumerable.Range(1, 1000).ToList(), i =>
{
Console.WriteLine(i);
using (var c = new HttpClient { Timeout = TimeSpan.FromMilliseconds(1) })
{
var t = c.GetAsync("http://microsoft.com");
t.RunSynchronously(); //<--comment this line and it crashes
Console.WriteLine(t.Result);
}
});
}
catch (Exception x)
{
Console.WriteLine(x.Message);
}
Console.ReadKey();
}
}
}

Categories