Greetings! I've stumbled upon what I believe to be a rather serious problem in mono's WCF implementation.
When a client disconnects during a transmission from a WebServiceHost, an exception is thrown: Exception Write failure at System.Net.Sockets.NetworkStream.Write (System.Byte[] buffer, Int32 offset, Int32 size) [0x0008e] in /build/mono/src/mono-3.12.0/mcs/class/System/System.Net.Sockets/NetworkStream.cs:418 at System.Net.ResponseStream.InternalWrite (System.Byte[] buffer, Int32 offset, Int32 count) [0x00029] in /build/mono/src/mono-3.12.0/mcs/class/System/System.Net/ResponseStream.cs:132 at System.Net.ResponseStream.Write (System.Byte[] buffer, Int32 offset, Int32 count) [0x000dd] in /build/mono/src/mono-3.12.0/mcs/class/System/System.Net/ResponseStream.cs:165 at System.ServiceModel.Channels.Http.HttpRequestContext.InternalReply (System.ServiceModel.Channels.Message msg, TimeSpan timeout) [0x00157] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpRequestContext.cs:160 at System.ServiceModel.Channels.Http.HttpRequestContext.Reply (System.ServiceModel.Channels.Message msg, TimeSpan timeout) [0x00000] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpRequestContext.cs:101 at System.ServiceModel.Dispatcher.MessageProcessingContext.Reply (Boolean useTimeout) [0x00026] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/MessageProcessingContext.cs:96 at System.ServiceModel.Dispatcher.OperationInvokerHandler.Reply (System.ServiceModel.Dispatcher.MessageProcessingContext mrc, Boolean useTimeout) [0x0001d] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/OperationInvokerHandler.cs:69 at System.ServiceModel.Dispatcher.OperationInvokerHandler.ProcessRequest (System.ServiceModel.Dispatcher.MessageProcessingContext mrc) [0x00044] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/OperationInvokerHandler.cs:29 at System.ServiceModel.Dispatcher.BaseRequestProcessorHandler.ProcessRequestChain (System.ServiceModel.Dispatcher.MessageProcessingContext mrc) [0x00000] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseRequestProcessorHandler.cs:15 at System.ServiceModel.Dispatcher.BaseRequestProcessorHandler.ProcessRequestChain (System.ServiceModel.Dispatcher.MessageProcessingContext mrc) [0x00017] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseRequestProcessorHandler.cs:16 at System.ServiceModel.Dispatcher.HandlersChain.ProcessRequestChain (System.ServiceModel.Dispatcher.MessageProcessingContext mrc) [0x0000b] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseRequestProcessor.cs:72 at System.ServiceModel.Dispatcher.BaseRequestProcessor.ProcessRequest (System.ServiceModel.Dispatcher.MessageProcessingContext mrc) [0x00018] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/BaseRequestProcessor.cs:26 This exception gets caught and rethrown until it ends up at /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ChannelDispatcher.cs:596, where ProcessErrorWithHandlers returns false and we reply to the RequestContext with an error message. This then generates a second exception that is not caught, crashing the whole program: Unhandled Exception: System.InvalidOperationException: Cannot be changed after headers are sent. at System.Net.HttpListenerResponse.set_ContentType (System.String value) [0x00027] in /build/mono/src/mono-3.12.0/mcs/class/System/System.Net/HttpListenerResponse.cs:110 at System.ServiceModel.Channels.Http.HttpStandaloneResponseInfo.set_ContentType (System.String value) [0x00000] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpContextInfo.cs:274 at System.ServiceModel.Channels.Http.HttpRequestContext.InternalReply (System.ServiceModel.Channels.Message msg, TimeSpan timeout) [0x00046] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpRequestContext.cs:140 at System.ServiceModel.Channels.Http.HttpRequestContext.Reply (System.ServiceModel.Channels.Message msg, TimeSpan timeout) [0x00000] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpRequestContext.cs:101 at System.ServiceModel.Channels.Http.HttpRequestContext.Reply (System.ServiceModel.Channels.Message msg) [0x00000] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpRequestContext.cs:96 at System.ServiceModel.Dispatcher.ListenerLoopManager.ProcessRequest (IReplyChannel reply, System.ServiceModel.Channels.RequestContext rc) [0x0003b] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ChannelDispatcher.cs:601 at System.ServiceModel.Dispatcher.ListenerLoopManager.TryReceiveRequestDone (IAsyncResult result) [0x0001a] in /build/mono/src/mono-3.12.0/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ChannelDispatcher.cs:575 I've attached an example that will trigger the problem if used to serve a large file over a network. As soon as the client cancels the transfer, the application will crash. In Microsoft .NET, no crash is observed. I would be very grateful if someone could comment on this issue. Apparently the problem has been reported before, but it seems no fix was implemented: https://bugzilla.xamarin.com/show_bug.cgi?id=5926 Is my example doing something that you're not supposed to do? It seems to me that the WebServiceHost functionality is completely unusable with this bug. Thanks and best regards, Alex
using System; using System.IO; using System.ServiceModel; using System.ServiceModel.Web; using System.Net; namespace ServerTest { [ServiceContract] public class WebService { public WebService() { } [OperationContract, WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/get")] public Stream GetFile(){ Stream f = File.OpenRead("test.dat"); return f; } } class MainClass { public static void Main(string[] args) { ServiceHost Host= new WebServiceHost(typeof(WebService),new Uri("http://localhost:3000/")); WebHttpBinding wb = new WebHttpBinding(); Host.AddServiceEndpoint(typeof(WebService), wb, ""); Host.Open(); Console.ReadLine(); Host.Close(); } } }
_______________________________________________ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list