anchor.diff:      end,
       {noreply, State#state{works=Works1}};
   
  -handle_info({'DOWN', _MRef, process, Pid, _Reason}, #state{services=Srvs}=State) ->
  +handle_info({'DOWN', _MRef, process, Pid, _Reason}, State) ->
  +    #state{name=Name, services=Srvs, works=Works} = State,
       case maps:find(Pid, Srvs) of
           {ok, {SrvId, CallPids}} ->
  -            lager:warning("Service ~p (~p) down", [SrvId, SrvId:name()]),
  -            State1 = do_service_down(CallPids, State),
  -            State2 = State1#state{services=maps:remove(Pid, Srvs)},
  -            {noreply, State2};
  -        false ->
  -            {noreply, do_call_down(Pid, State)}
  +            % A service is down
  +            lager:info("Service ~p (~p) down at ~p. Calls: ~p", 
  +                          [SrvId, SrvId:name(), Name, CallPids]),
  +            lists:foreach(fun(CallPid) -> gen_server:cast(CallPid, stop) end, CallPids),
  +            State1 = State#state{services=maps:remove(Pid, Srvs)},
  +            {noreply, State1};
  +        error ->
  +            % A call is down
  +            State1 = remove_call(Pid, State),
  +            State2 = case maps:find(Pid, Works) of
  +                {ok, {SrvId, CallId, WorkList}} -> 
  +                    % We had pending work for this process.
  +                    % Actually, we know the process has stopped normally before processing
  +                    % these requests (it hasn't failed due to an error).
  +                    % If the process had failed due to an error processing the work,
  +                    % the "received work" message would have been received an the work will
  +                    % not be present in Works.
  +                    St = State1#state{works=maps:remove(Pid, Works)},
  +                    resend_worklist(SrvId, CallId, lists:reverse(WorkList), St);
  +                error ->
  +                    State1
  +            end,
  +            {noreply, State2}
       end;
   
   handle_info(Info, State) -> 
  
positive.code: 
  
  %% @private
  -spec do_call_down(pid(), #state{}) ->
      #state{}.
  
  do_call_down(CallPid, State) ->
      #state{pos=Pos, name=Name, works=Works, services=Srvs} = State,
      Srvs1 = case ets:lookup(Name, CallPid) of
          [{CallPid, RefId}] ->
              {_, SrvId, CallId} = RefId,
              ?debug(SrvId, CallId, "Router ~p unregistering call", [Pos]),
              ets:delete(Name, CallPid), 
              ets:delete(Name, RefId),
              {SrvId, Calls} = maps:get(SrvId, Srvs),
              maps:put(SrvId, Calls -- [CallPid], Srvs);
          [] ->
              Srvs
      end,
      case maps:find(CallPid, Works) of
          {ok, {SrvId1, CallId1, WorkList}} -> 
              % We had pending work for this process.
              % Actually, we know the process has stopped normally before processing
              % these requests (it hasn't failed due to an error).
              % If the process had failed due to an error processing the work,
              % the "received work" message would have been received an the work will
              % not be present in Works.
              State1 = State#state{services=Srvs1, works=maps:remove(CallPid, Works)},
              resend_worklist(SrvId1, CallId1, lists:reverse(WorkList), State1);
          error ->
              State#state{services=Srvs1}
      end.
  
  
  %% @private
  -spec do_service_down([pid()], #state{}) ->
      #state{}.
  
  do_service_down([], State) ->
      State;
  
  do_service_down([CallPid|Rest], #state{name=Name, works=Works}=State) ->
      gen_server:cast(CallPid, stop),
      case ets:lookup(Name, CallPid) of
          [{CallPid, CallId}] ->
              ets:delete(Name, CallPid), 
              ets:delete(Name, CallId);
          [] ->
              ok
      end,
      Works1 = maps:remove(CallPid, Works),
      do_service_down(Rest, State#state{works=Works1}).
  
  
  %% @private
  -spec find(atom(), nksip:srv_id(), nksip:call_id()) ->
      {ok, pid()} | not_found.
  
  find(Name, SrvId, CallId) ->
      case ets:lookup(Name, {call, SrvId, CallId}) of
          [{_, Pid}] -> {ok, Pid};
          [] -> not_found
      end.
  
  %% @private
  work_id(Tuple) when is_tuple(Tuple) -> element(1, Tuple);
  work_id(Other) -> Other.
  
  
  %% @private
  
negative.code:             case nklib_counters:value({nksip_calls, SrvId}) < SrvMax of
                  true ->
                      {ok, CallPid} = nksip_call_srv:start(SrvId, CallId),
                      State1 = save_call(SrvId, SrvPid, CallId, CallPid, State),
                      do_send_work_sync(CallPid, SrvId, CallId, Work, From, State1);
                  false ->
                      {error, too_many_calls}
  