4

I am getting an exception when trying to servialize the .NET ServiceController class. It serializes fine when it's null but once I populate it I get a stackoverflow exception.

So this works:

    [DataMember]
    public ServiceController MyServiceController
    {
        get { return null; }
    }

But this gives the error "An unhandled exception of type 'System.StackOverflowException' occurred in System.ServiceProcess.dll":

public class TestClass
{
    private ServiceController _serviceController;
    [DataMember]
    public ServiceController MyServiceController
    {
        get { return ServiceController.GetServices()[0];
    }
}

A strange thing is that there is no error in the logs at all. When there is an error I can see it in the logs so it's not because my logs aren't working. Here is my config file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyCompany.Wcf.RdbmsServer.RdbmsServiceBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="MyCompany.Wcf.RdbmsServer.RdbmsServiceBehavior"
        name="MyCompany.Wcf.RdbmsServer.RdbmsService">
        <endpoint address="" binding="wsHttpBinding" contract="MyCompany.Wcf.RdbmsServer.IRdbmsService" bindingConfiguration="IncreaseMaxMessageSize">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8731/Design_Time_Addresses/MyCompany.Wcf.RdbmsServer/RdbmsService/" />
          </baseAddresses>
        </host>
      </service>
    </services>

    <bindings>
      <wsHttpBinding>
        <binding name="IncreaseMaxMessageSize" 
            maxReceivedMessageSize="655360000">
        </binding>
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="All"
              propagateActivity="true">
        <listeners>
          <add name="traceListener"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData= "c:\Traces.svclog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

</configuration>

Here is my service interface

[ServiceContract]
public interface IRdbmsService
{
    [OperationContract]
    TestClass GetServiceControllerList();
}

And the implementation is:

    public TestClass GetServiceControllerList()
    {
       return new TestClass();
    }

Any ideas?

Bob
  • 4,236
  • 12
  • 45
  • 65
  • 1
    What is in the ServiceController constructor? I also think the idea of calling a property same as class has caused this in the WSDL. – Aliostad Dec 15 '10 at 13:39
  • There is nothing in the ServiceController constructor, it's a .NET framework class i.e. System.ServiceProcess.ServiceController. I also changed the prop name and same error – Bob Dec 15 '10 at 14:17
  • StackOverflowException cannot be logged, because it cannot be catched in the code. – nothrow Dec 15 '10 at 14:28

2 Answers2

3

You are causing the serializer to recurse:

public class TestClass
{
    private ServiceController _serviceController;
    [DataMember]
    public ServiceController MyServiceController
    {
        get { return ServiceController.GetServices()[0]; // <-- this returns your service
    }
}

The service this is returning is your IRdbmsService, which returns TestClass. This then needs to be serialized, etc.

Edit: To clarify:

When TestClass is serialized, the serializer looks at all of its DataMember properties, one of which is ServiceController. It then serializes this property, which does this on the get:

return ServiceController.GetServices()[0];

Since IRdbmsService is the only service defined in your scope, it is at index 0 from the response of the GetServices call, so it then must be serialized. Since the return type of GetServiceControllerList is TestClass, TestClass must then be serialized, which brings us back to the beginning (hence, the recursion).

As far as how to go about solving this, it depends on what you are trying to do. What this service is doing at the moment is returning information about itself to the caller, which doesn't make sense to me; the caller already has this information at the time of consumption (before making the call). Can you clarify your intent?

Mark Avenius
  • 13,679
  • 6
  • 42
  • 50
  • Hi Mark, can you please explain further as i'm not sure what you mean? Is the first time when TestClass gets initalized and second time when TestClass gets serialized? If so why would this even cause a StackOF exception, what's wrong with calling ServiceController.GetServices()[0] twice? (besides doing extra work of course) And how do i fix this? – Bob Dec 15 '10 at 14:46
  • Ah i didn't realise that .GetServices()[0] was returning my WCF Service. I tryed with "return new ServiceController("Windows Installer")" but now I get another error. I'll ask it in another Q. thanks a lot – Bob Dec 15 '10 at 15:48
0

Yes, in the constructor of ServiceController CLASS, you are problably calling something recursive which don't have a condition to stop, so every time it calls something recursive, the program push to a stack, and as I said there is no stop condition, it will add to stack untill the memory explode, so it gives this error name StackOverFlow.

A suggestion: Add a break point to debug where its calling recursive. It's so easy when debugging.

alansiqueira27
  • 8,129
  • 15
  • 67
  • 111
  • Hi Alan, that's not it i'm afraid. I broke it down so that the only thing returned from the service is a clas with 1 property in the getting of the propert I have return ServiceController.GetServices()[0]; ..... so no recursive stuff going on at all. Maybe there is something I need to change besides the maxReceivedMessageSize? – Bob Dec 15 '10 at 13:53
  • Hi, it's hard to tell without the code. I REALLY sugest you to put a breakpoint at the begin and debug to see where it goes recursive. It's easy! – alansiqueira27 Dec 15 '10 at 14:00
  • Hi Alan, i edited the question will ALL the code i use. I did the breakpoint thing u suggested and there is definitly nothing recursive happening. The ServiceController class in a framework class in System.ServiceProcess.ServiceController. Any other ideas? – Bob Dec 15 '10 at 14:25
  • Search for stackoverflow at MSDN, maybe there is another reason. – alansiqueira27 Dec 15 '10 at 14:45