                     process.kill(child.PID)
                 @process.kill()
 
+    state: (newState) =>
+        # Keeps track of state and runs certain state-transition tasks
+        oldState = @__state
+        if not newState?
+            console.log "oldState requested"
+            return oldState
+        if newState not in ['stopped', 'starting', 'running']
+            throw new Error("Invalid state #{newState}")
+        console.log "#{oldState} -> #{newState}"
+        @__state = newState
+
+        # state-transition tasks
+        if oldState == 'starting'
+            if newState == 'running'
+                for callback in @readyCallbacks
+                    callback()
+            @readyCallbacks = []
+
 module.exports =
     ServiceManager: ServiceManager
     Service: Service

        @port = null
        @process = null
        @stopTimeout = null
        @state = @states.stopped
        @readyCallbacks = []

    states:
        stopped: 0
        starting: 1
        running: 2

    start: (readyCallback) =>
        if @stopTimeout?
            clearTimeout @stopTimeout
        @stopTimeout = setTimeout @stop, @serviceManager.config.timeout

        if @state == @states.running
            readyCallback()
            return
        if @state == @states.starting
            @readyCallbacks.push readyCallback
            return

        @state = @states.starting


        freeport (err, port) =>
            @port = port
            processName = "#{@serviceManager.config.dir}/#{@name}"

                        testClient.end()
                    testClient.on 'end', () =>
                        # ready to run
                        @state 'running'
                    testClient.on 'error', (e) ->
                        if e.code in ['ECONNREFUSED']
                            setTimeout tester, 1000
