Shared Services

One of the comments I made when doing my “first impressions” of the Mirra backup device was that the Windows software starts two separate services running in two different processes.

I see this a lot – people architect their product into multiple services (which is often a good thing), but they then run the services in separate processes.

Sometimes this is a good thing – for example, the Windows Media Connect add-on for Windows runs as two services – one service does very little, but runs as LocalSystem (full privileges).  The other service (which does most of the work) runs in a limited LocalService account.  By running as two services, in two different privilege levels, the Windows Media Connect carefully limits which functionality has to run with elevated privileges.  This is a good example of the principle of least privilege – isolate the parts of the functionality that need higher privileges and run them out-of-proc instead of running the entire service with elevated privileges.

But sometimes it doesn’t really make sense.  Mirra is a good example, and there are others as well.  These products have multiple Windows Services, which run in the same security context, but use separate processes.

Why is this a big deal?  Well, unlike *nix, on Windows, a process is a relatively expensive entity.  It takes a non trivial amount of time to launch a process, and each process consumes a fair amount of system resources (something like 1M of virtual memory, just for the various process structures (virtual address map, handle table, etc), IIRC).  Each process running drains the system of resources that could be used for your application, so it’s important to reduce the number of system processes running.  It always annoys me when I install some application and discover that it’s installed three or four processes that run all the time on my machine, especially when those functions could have been combined into a single process.

For services, this is especially annoying – the NT service controller has had support for shared services built-in since NT 3.1.

You can see shared services in action on any Windows machine.  If you have the SDK tool tlist.exe, you can run “tlist -s” and see the services running in each process.  On my machine, tlist shows (among other things):

1280 svchost.exe Svcs: AudioSrv,BITS,CryptSvc,Dhcp,dmserver,ERSvc,EventSystem,helpsvc,lanmanserver,lanmanworkstatio

In this example, svchost.exe is running 26 different services.  Without shared services, each of these would be a separate process, thus consuming a huge chunk of resources.  In fact, that’s the entire purpose of svchost – it provides a common hosting framework for Windows to use for shared services.  svchost.exe is an internal-only facility, but the functionality on which it is based is available for everyone.  To specify a service as being a shared service, all you need to do is to specify the dwServiceType as SERVICE_WIN32_SHARE_PROCESS when you call CreateService and the service controller will do “the right thing”.

You need to do a smidge more work – if you’re a shared service, then when you call StartServiceCtrlDispatcher, you need to specify all the services that will be running in your process, but that’s about it. 

When you ask the service controller to start a share process service, the service controller first looks to see if that service is started.  If it’s not, it looks at the running service control dispatchers to see if there’s a dispatcher running for the new service.  If there is a dispatcher running for the service, then it uses that dispatcher to start the new service, if there isn’t, it launches the process that was specified in the lpBinaryPathName parameter to CreateService.

The bottom line is that if you’re responsible for more than one service (or your product contains more than one service), you should seriously consider combining them into a single process – it’s not that much extra effort, and the benefits can be huge.

Comments (13)

  1. Steve Eck says:

    The built-in Windows XP and 2003 utility tasklist.exe can also show the services hosted in a process.

    "tasklist /svc" will show similar information to "tlist -s".

  2. Stefan Kuhr says:

    I’ve written a service hosting framework for our company that allows running multiple services in one process via one DLL per each service and we did it for the exact reasons you gave: system resources. But Larry: If shared process services are such a darn good thing, why then doesn’t MS document the svchost.exe interfaces so ISVs could use it as well?

  3. Stephen Veiss says:

    One advantage of running services in their own processes is that it’s an awful lot easier to figure out which service is causing a problem and fix it if they’re running in separate process.

    An example: about a week ago, something made one of the WMI services on my machine go haywire. The first indication I had of a problem was the Virtual Memory Low warning message box that Windows displays when forced to increase the size of the swap file.

    I checked in Task Manager, which showed that the machine had about 2.5Gb allocated, and about 1.5Gb of that was being used by a svchost.exe process.

    Some playing with tasklist /svc and SysInternal’s Process Explorer showed that it was the svchost -k netsvcs instance, which is currently hosting 31 services on my machine. Process Explorer also showed that threads were being created and destroyed at around one-second intervals, and the function name displayed was a Wbem* function.

    It seemed to be creating and destroying threads at a rate of around one per second, and leaking some memory along with it. Restarting the WMI services stopped the leak from getting worse… but didn’t return the allocated 1.5Gb to the system.

    Compounding the problem somewhat is the fact that not all the services running in that instance of svchost.exe will respond to stop requests. After trying a couple of times to stop and restart them all, I ended up having to stop work and reboot the machine. This was on my personal workstation, so an unexpected reboot isn’t a big deal – but it’d be a little more serious if a similar problem occurred on a production server.

    Of course, you’d hope that you’d never find a memory leak in production anyway, but it happens. When it does, I’d like to be able to restart the offending process whilst affecting as little else as possible. Shared services make that task harder.

  4. LarryOsterman says:

    Stefan, that’s a good question. The answer is that people would start putting 3rd party code in the same process as the built-in services.

    And that in turn turns into a reliability nightmare – when an instance of svchost.exe goes down, it takes out all the services within the svchost, which can totally tank a system.

  5. Shiv says:

    I’ve noticed the same problem as Stephen Viess and have come to the conclusion that perhaps the benefit of running many services in one svchost.exe aren’t as great as touted. Once I also had the "svchost -k netsvcs" process running away with more memory than usual. I thought that perhaps restarting the offending service would fix it. But how does one find out which one is the culprit? After hunting around with various tools I gave up and started restarting all the services inside it one by one. Guess what? Just like Stephen mentioned it didn’t make any difference! The memory usage remained the same (actually increased by a few %). Something isn’t quite right in the svchost mechanism. There should be tools to figure out which service is running away and some way to reclaim its resources. Without that IMHO it might be better to have more processes. After all RAM is cheap these days :) It might make sense to do svchost for some common related services. But IMO "svchost -k netsvcs" is quite the extreme counterproductive example.

  6. Cheong says:

    After reading the MSDN page of CreateService, may I ask one question?

    The article states that the "SERVICE_INTERACTIVE_PROCESS" attribute requires LocalSystem security context. But is it possible to create serivce that can be interactive with desktop, yet just run in normal user account?

    For example, if I’m writing a FTP server, I think a normal user account for that ftproot folder could be enough.

  7. LarryOsterman says:

    Cheong, do a google search for "shatter attack" before you consider deploying a service with the SERVICE_INTERACTIVE_PROCESS flag.

    Also note that the SERVICE_INTERACTIVE_PROCESS flag doesn’t work correctly in FUS scenarios (the UI only pops up on session 0).

    For Vista, your service is highly unlikely to work correctly do to some significant security work that’s been done to mitigate shatter attacks. You don’t want to EVER pop UI up from a service.

  8. Andreas Häber says:

    Interactive services are not available anymore in Vista. From the release notes[1]:

    "The concept of interactive services is being phased out, starting with Windows Vista versions of Windows. Session 0 is now reserved for services and system processes, and users can no longer interactively log on to session 0. Services that assume session 0 is an interactive session might no longer work correctly. Windows and dialog boxes that were displayed directly from services will not be visible to the user, and the service might stop responding if the user interface (UI) requires user input."

    One thing I like with interactive services are for global hotkeys. For example I have one interactive service which registers a hotkey for the ctrl+| (pipe) keys. When this hotkey is fired then the service will move the current window from one monitor over to another one. You could do this with an application running from the taskbar too, but I really dislike using the taskbar for stuff which are supposed to be running in the background.


  9. Ben says:

    >>You don’t want to EVER pop UI up from a service. <<

    What about launching another "normal" program from a service, perhaps using CreateProcessAsUser? Does the same rule apply? Any implications from Vista on that?

  10. LarryOsterman says:

    CPAU will continue to work, it doesn’t have the security problems that interactive services have.

  11. Cheong says:

    Yes. There is security consideration on allowing a process that run with high privellege to interact with user. That what causing me think to lowering it(i.e. a normal user account will do in many case).

    And controlling the behaviour within the same application is much more simple than using another program to control it.

  12. The last time I wrote, I talked about shared services. One of the problems of working with shared services…