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

Reply via email to