Program: 103117
Project: 103117
Buggy source:
/** 
 * Method to schedule a reconnect for a protocol provider.
 * @param pp the provider.
 */
private void reconnect(final ProtocolProviderService pp){
  long delay;
  if (currentlyReconnecting.containsKey(pp)) {
    delay=currentlyReconnecting.get(pp).delay;
    delay=Math.min(delay * 2,MAX_RECONNECT_DELAY * 1000);
  }
 else {
    delay=(long)(RECONNECT_DELAY_MIN + Math.random() * RECONNECT_DELAY_MAX) * 1000;
  }
  final ReconnectTask task=new ReconnectTask(pp);
  task.delay=delay;
  RegistrationStateChangeListener listener=new RegistrationStateChangeListener(){
    public void registrationStateChanged(    RegistrationStateChangeEvent evt){
      if (evt.getSource() instanceof ProtocolProviderService) {
        if (evt.getNewState().equals(RegistrationState.UNREGISTERED) || evt.getNewState().equals(RegistrationState.CONNECTION_FAILED)) {
synchronized (this) {
            pp.removeRegistrationStateChangeListener(this);
            if (timer == null)             return;
            if (connectedInterfaces.size() == 0) {
              needsReconnection.add(pp);
              if (currentlyReconnecting.containsKey(pp))               currentlyReconnecting.remove(pp).cancel();
              return;
            }
            if (currentlyReconnecting.containsKey(pp))             currentlyReconnecting.remove(pp).cancel();
            currentlyReconnecting.put(pp,task);
            if (logger.isTraceEnabled())             logger.trace("String_Node_Str" + pp + "String_Node_Str"+ task.delay+ "String_Node_Str");
            timer.schedule(task,task.delay);
          }
        }
      }
    }
  }
;
  pp.addRegistrationStateChangeListener(listener);
  unregister(pp,true,listener,task);
}

Fixed version (ground truth):
/** 
 * Method to schedule a reconnect for a protocol provider.
 * @param pp the provider.
 */
private void reconnect(final ProtocolProviderService pp){
  long delay;
  if (currentlyReconnecting.containsKey(pp)) {
    delay=currentlyReconnecting.get(pp).delay;
    delay=Math.min(delay * 2,MAX_RECONNECT_DELAY * 1000);
  }
 else {
    delay=(long)(RECONNECT_DELAY_MIN + Math.random() * RECONNECT_DELAY_MAX) * 1000;
  }
  final ReconnectTask task=new ReconnectTask(pp);
  task.delay=delay;
  RegistrationStateChangeListener listener=new RegistrationStateChangeListener(){
    public void registrationStateChanged(    RegistrationStateChangeEvent evt){
      if (evt.getSource() instanceof ProtocolProviderService) {
        if (evt.getNewState().equals(RegistrationState.UNREGISTERED) || evt.getNewState().equals(RegistrationState.CONNECTION_FAILED)) {
synchronized (this) {
            pp.removeRegistrationStateChangeListener(this);
            if (timer == null)             return;
            if (connectedInterfaces.size() == 0) {
              needsReconnection.add(pp);
              if (currentlyReconnecting.containsKey(pp))               currentlyReconnecting.remove(pp).cancel();
              return;
            }
            if (currentlyReconnecting.containsKey(pp))             currentlyReconnecting.remove(pp).cancel();
            currentlyReconnecting.put(pp,task);
            if (logger.isInfoEnabled())             logger.info("String_Node_Str" + pp.getAccountID().getDisplayName() + "String_Node_Str"+ task.delay+ "String_Node_Str");
            timer.schedule(task,task.delay);
          }
        }
      }
    }
  }
;
  pp.addRegistrationStateChangeListener(listener);
  unregister(pp,true,listener,task);
}