When developing Window Service Apps, what is the difference between stop and pause?
Do developers distinguish between the two?
When a service is paused, it can maintain internal state, including cached information or possibly even a queue of waiting work items. The service can then be resumed to pick up where it left off.
If the service is stopped, internal state is discarded. Starting the service again should repeat all initialization.
Developers do distinguish between the two. The distinction is very important when a service has a non-trivial initialization process.
For more information on `service states' see Introduction to Windows Services
Related
We are conducting an experiment to gauge the benefits of service worker. As part of that we are recording pageLoadTime and service worker state. The idea is that the data which has controller state as activated will be treated as pages served via service worker and where service worker is not installed will have controller as null and so no service worker state. This way we can compare pageLoadTime with & without service worker.
Is this the right approach to know that the page is being served from SW? One concern that comes to mind is, if SW gets killed in between and gives us wrong info about the state. However we are recording service worker state way early in page load lifecycle as soon as our js code boots up. So at this point SW should be up & running intercepting traffic from the page. This looks to be a safe technique. Any thoughts are this ?
Another approach that comes to mind after reading PerformanceResourceTiming API on MDN is to use workerTime.
The workerStart read-only property of the PerformanceResourceTiming interface returns a DOMHighResTimeStamp
immediately before dispatching the FetchEvent if a Service Worker
thread is already running, or immediately before starting the Service
Worker thread if it is not already running. If the resource is not
intercepted by a Service Worker the property will always return 0.
As per the doc, it mentions workerTime will always be zero if SW is not there. Can there be a scenario when SW is installed and yet workerTime is zero?
As an trial, I crawled to Pinterest and queried following in Chrome dev console, workerTime is always zero though SW is there.
performance.getEntriesByType('navigation')[0]
For your own applications, where you're in control of the code that registers the service worker, the best way to determine whether a service worker was in control of the page at load time is to check navigator.serviceWorker.controller before you call navigator.serviceWorker.register(). If navigator.serviceWorker.controller is not null that means a service worker was in control when the page was loaded.
Note, it's important to check navigator.serviceWorker.controller before registering your service worker, because a service worker can start controlling the page after it's registered (if it calls clients.claim()) but in such cases it wasn't controlling the page at load time, which is what you care about.
On my website, here's the code I use on my blog to determine the initial service worker state:
export const initialSWState = !navigator.serviceWorker ? 'unsupported' :
navigator.serviceWorker.controller ? 'controlled' : 'supported';
And since this code runs in the initial evaluation of the module, I know it runs before I register my service worker (which I postpone until after the load event.
One concern that comes to mind is, if SW gets killed in between and gives us wrong info about the state.
That's not a problem. When a service worker is in control of a page, navigator.serviceWorker.controller will always return a reference to that service worker, even if it's not currently running.
As per the doc, it mentions workerTime will always be zero if SW is not there. Can there be a scenario when SW is installed and yet workerTime is zero?
Yes there can. Looking at my own analytics data over the last 30 days, I see a 0 value for workerStart in 14.5% of cases where I knew (using the above technique) that the service worker was in control at page load time. And of 14.5%, almost all of them were either Firefox or Safari, so it looks like those browsers don't correctly set the workerStart value.
I have a Windows Service which has several timer jobs in it. In the OnStart method, I am starting all those timers. In effect, it takes a lot of time starting the service from the Services console and most of the time, it reports this:
Windows could not start the 'servicename' service on Local Computer.
The service did not repond to the start or control request in a timely fashion.
I know I could create a timer which encapsulatesthe other timers so I could start them outside the OnStart event. However, I'm looking for other possible solutions as I don't like the idea of having a separate timer which does nothing other than start the other processes.
It isn't generally safe to perform external operations such as web or database calls during OnStart, because you can't predict how long they will take, and an excessively long service startup time can interfere with the system:
The Service Control Manager (SCM) waits until the service reports a status of SERVICE_RUNNING. It is recommended that the service reports this status as quickly as possible, as other components in the system that require interaction with SCM will be blocked during this time. Some functions may require interaction with the SCM either directly or indirectly.
So the proper solution is to move this initialization into a separate thread.
However, if you don't want to do this, you can call RequestAdditionalTime:
The RequestAdditionalTime method is intended to be called by the overridden OnContinue, OnPause, OnStart, or OnStop methods to request additional time for a pending operation, to prevent the Service Control Manager (SCM) from marking the service as not responding.
I've successfully followed the Daemons and Service Guide - Creating XPC Services tutorial, along with the SandboxedFetch sample code and have a working Client / Service setup that is using the new NSXPCConnection class.
What still isn't entirely clear to me is how to properly self-terminate the service application once it has finished its job. I recognize that in many cases, the service is expected to remain alive, but in the use-case I have in mind, the service will be used to only to do some processing that I'd otherwise not perform in the main application. Once that processing is finished, there's no reason for the service application to remain. If the client needs another service at a later date, it can just re-create a new one.
Since the service is a lightweight, non-nibbed, NSApplication, I was trying to self-terminate it by calling invalidate from inside applicationWillTerminate, but that triggers an EXC_BAD_ACCESS exception almost every time. Calling invalidate on the service's [NSXPCListener serviceListener] generates slightly less reliable crashes, but it still crashes.
Calling invalidate from within the client application on its NSXPCConnection also generates an EXC_BAD_ACCESS exception almost every time.
So I'm curious what the correct sequence of steps is to cleanly shutdown the XPC service and then quit the service application. Ideally, the service would self-terminate after it has made its last XPC call to the client.
Attached is a small screenshot of what one of the exception's stacktrace looks like. (Yes, that's a webview that's loading in the service. Once the webview has finished loading, I want the service to self-terminate)
My first reaction is that you should not bother to terminate. When memory pressure occurs and your service is idle, launchd will kill your service. Exiting probably isn't in anyone's best interest because your service will take time to launch again. Don't terminate and you won't have to figure out why your attempt crashes.
But if for some reason you are determined to terminate, don't try so hard. Just do whatever you need to do to clean up (flush buffers, close network connections gracefully so the server doesn't suffer, whatever) and call exit. Although you seem to be using NSApplication, your service is not an application in any sense that the user cares about and there is no compelling reason to act like one in this respect. The host application needs to be able to cope with your service crashing anyway, so your deliberately exiting unceremoniously is just fine.
By the way, using NSApplication in an XPC service probably isn't the best idea because there's no supported way to declare that you want that. This might help explain why it isn't working as well as you'd like, though this paragraph should not be construed as a proper analysis of the crash. :-)
I have an app which needs almost no user interaction, but requires Geofences. Can I run this entirely within a background service?
There will be an Activity when the service is first run. This Activity will start a service and register a BroadcastReceiver for BOOT_COMPLETED, so the service will start at boot. It's unlikely that this Activity will ever be run again.
The service will set an Alarm to go off periodically, which will cause an IntentService to download a list of locations from the network. This IntentService will then set up Geofences around those locations, and create PendingIntents which will fire when the locations are approached. In turn, those PendingIntents will cause another IntentService to take some action.
All this needs to happen in the background, with no user interaction apart from starting the Activity for the first time after installation. Hence, the Activity will not interact with LocationClient or any location services.
I've actually got this set up with proximityAlerts, but wish to move to the new Geofencing API for battery life reasons. However, I have heard that there can be a few problems with using LocationClient from within a service. Specifically, what I've heard (sorry, no references, just hearsay claims):
location client relies on ui availability for error handling
when called from background thread, LocationClient.connect() assumes that it is called from main ui thread (or other thread with event looper), so connection callback is never called, if we call this method from service running in background thread
When I've investigated, I can't see any reason why this would be the case, or why it would stop my doing what I want. I was hoping it would be almost a drop-in replacement for proximityAlerts...
Can anyone shed some light on things here?
The best thing would be to just try it out, right? Your strategy seems sound.
when called from background thread, LocationClient.connect() assumes that it is called from main ui thread (or other thread with event looper), so connection callback is never called, if we call this method from service running in background thread.
I know this to be not true. I have a Service that is started from an Activity, and the connection callback is called.
I dont know about proximity alerts; but I cant seem to find an API to list my GeoFences. I am worried that my database (sqlite) and the actual fences might get out of sync. That is a design flaw in my opinion.
The reason LocationClient needs UI, is that the device may not have Google Play Services installed. Google has deviced a cunning and complex mechanism that allows your app to prompt the user to download it. The whole thing is horrible and awful in my opinion. Its all "what-if what-if" programming.
(They rushed a lot of stuff out the door for google IO 2013. Not all of it are well documented, and some of it seems a bit "rough around the edges").
sc query state= all works as expected from the command line.
From within another Service, sc query state= all doesn't print anything to that sub-process' stdout (captured by the parent, of course).
Is there a permission/privilege that the Service needs in order to list/start/stop the other servies?
A little background: I am making a service that periodically restarts some misbehaving services.
Well, for one don't do that, at least not in a blocking manner. In order for your own service to respond to the SCM (Service Control Manager) in order to return its status, the service has to be able to execute its dispatcher code. This means that if you call this program and wait for it to exit you'll wait indefinitely. One way to mitigate this would be to put this into a separate thread so it's not blocking your dispatching and your service will continue to talk to the SCM.
Alternatively (and probably better) you could use the EnumServicesStatusEx function to talk to the SCM and inquire about the statuses of other services yourself. The function itself doesn't mention anything about being blocking, so you'd have to figure out yourself whether it is and then use a thread again to prevent your service from stopping to talk to the SCM.
One last note: if those misbehaving services are yours, you should more likely fix the respective code. I've had a share of legacy code and had one misbehaving service which got its own helper application as "fault action" (can be configured in service configuration as SERVICE_CONFIG_FAILURE_ACTIONS) that would go about and restart the service whenever it crashed. Once I took that code over, figured out the cause and fixed it, the service was stable again and that application isn't really needed anymore.