- javadoc of Service interface and AbstractService so as to more clearly specify the desired behaviour of implementations.
- common methods in AbstractService to interrupt a non-null thread, stop non-null IPC and webapp servers. These calls return null values to overwrite field variables after the successful operation.
- static methods to stop a service if non null, and one to do it with exceptions caught and logged.
All subclasses have been reviewed and their stop operations
- use the new common interrupt and stop methods where appropriate
- use checks for null fields before trying any stop operation
- nullify all non-final fields after their work.
but not all of the stop() methods join onto the thread that was just interrupted; to wait for it to stop. This would be the cleanest option, as it guarantees the worker threads will not invoke a (now-stopped) service. I have not changed the behaviour of any existing services that do not perform Thread.join() operations. If there was a well defined behaviour for that join (time to wait, exception to throw on failure), it could be injected into the new AbstractService.interruptThread() method, and used throughout the services. Having a consistent interrupt/join/report failure process would imply only one thing to test, and more trust that new services will follow the examples set in the MRv2 codebase.
This patch does nothing to address the issue of MAPREDUCE-3535 -that the stoppability of a service is not checked before child classes terminate; it is somewhat orthogonal.
This patch is designed to ensure that no matter when Service.stop() is called (except in the special situation of a re-entrant call on a separate thread), everything is shut down cleanly. This means that even if the failure is triggered halfway through the init(Conf) or start() operations the stop() operation will always clean up what there is.