title: Zcontext.destroy() hangs instead of terminating all open sockets
body: <p>I have a server written in Java - (that uses ZeroMQ in REQ-REP and PUB-SUB patterns.) I am wrapping it as a Windows services using the Apache Commons Daemon (prunsrv/procrun)</p>
  
  <p>Sometimes the call to ZContext.destroy hangs. I have managed to get stack traces when the context is not destroyed. If I understand correctly, ZContext.destroy() should manage the termination of all sockets. What could be the problem?</p>
  
  <p>I have pasted the stack trace received when the context does not get destroyed - but we must end the process.</p>
  
  <pre><code>import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  import java.util.concurrent.Executors;
  import java.util.concurrent.ScheduledExecutorService;
  import java.util.concurrent.TimeUnit;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.zeromq.ZContext;
  import org.zeromq.ZMQ;
  
  /**
   * This is the driver for starting and stopping the PowerLoggerService
   * 
   */
  public class PowerLoggerService {
  
      static PreferenceManager prefMgr;
      static ModuleServer moduleServer;
      static DiscoveryServer discoveryServer;
      static LoggerRequestServer loggerRequestServer;
      static NotificationServer notificationServer;
      static ScheduledExecutorService scheduler;
      static ZContext zContext;
  
      private static final Logger log = LoggerFactory.getLogger("PowerLoggerService");
      private volatile static boolean shouldStop;
      private volatile static boolean contextWasDestroyed = false;
  
      public static void start(String [] args) {
  
          zContext = new ZContext();
          zContext.setLinger(0);
  
          scheduler = Executors.newScheduledThreadPool(1);
          log.trace("Entered startPMServer");
          notificationServer = new NotificationServer(zContext);
          notificationServer.publishStatus(MessageType.STARTED, "Server started");
  
          if(prefMgr.ensureValidDBPrefs()) {
              moduleServer = new ModuleServer();
              moduleServer.start();
              discoveryServer = new DiscoveryServer();
              discoveryServer.start();
  
              loggerRequestServer = new LoggerRequestServer(zContext);
              loggerRequestServer.start();                
              scheduler.scheduleAtFixedRate(notificationServer, 0, 10, TimeUnit.SECONDS);
          }
          else {
              log.error("Could not ensure that we have valid DB preferences ... need to exit.");
              System.exit(1);
          }
  
          while(!PowerLoggerService.shouldStop){
              log.trace("Value of boolean stop in start function: {}", PowerLoggerService.shouldStop);
              try {
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  log.error("PowerLoggerService main thread interrupted while sleeping");
              }
              log.trace("PowerLoggerService is running.");
              //printAllStackTraces();
          }
          //Sometimes the ZContext is not destroyed and the process goes to STOP_PENDING
          //the root cause needs to be found out and fixed - for now we are brute forcing
          //a System.exit
          if(contextWasDestroyed == false) {
              log.error("The context was not destroyed cleanly so we are doing a forced exit");
              printAllStackTraces();
              System.exit(-1);
          }
  
          log.debug("Stop was set to true and we are now exiting the start function!");
      }
  
      private static void printAllStackTraces() {
          StringBuilder sb = new StringBuilder();
          log.trace("=========================START TRACE");
          Map liveThreads = Thread.getAllStackTraces();
          sb.append("\n");
  
          for (Iterator i = liveThreads.keySet().iterator(); i.hasNext(); ) {
              Thread key = (Thread)i.next();
              sb.append("==============&gt;Thread ").append(key.getName()).append("\n");
              StackTraceElement[] trace = (StackTraceElement[])liveThreads.get(key);
              for (StackTraceElement trace1 : trace) {
                  sb.append("\tat ").append(trace1).append("\n");
              }
          }
  
          log.trace(sb.toString());
          log.trace("=========================END TRACE");
      }
  
      public static void stop() {
          try {
              log.info("Going to stop the PowerLoggerService");
              discoveryServer.shutDown();
              moduleServer.shutDown();
              loggerRequestServer.shutDown();
              notificationServer.shutDown();
  
              log.trace("In stop method after shutting down notification server");
              scheduler.shutdown();
              try {
                  log.trace("Terminated ?: {}",scheduler.awaitTermination(3, TimeUnit.SECONDS));
              } catch (InterruptedException ex) {
                  log.error("Interrupted when awaiting termination",ex);
              }
  
              List&lt;Runnable&gt; waiters = scheduler.shutdownNow();
              log.debug("Notification scheduled tasks that were waiting to be cancelled: {}", waiters.size());
              log.debug("Going to destroy the context");
  
              log.trace("going to set stop to true");
              PowerLoggerService.shouldStop = true;
              log.trace("stop is set to {}", PowerLoggerService.shouldStop);
              //printAllStackTraces();
              zContext.destroy();
              contextWasDestroyed = true;
              log.trace("AFTER context is destroyed");
          }
          catch (Exception e) {
              log.error("Unhandled exception when trying to shut down server ... We are going to have an unclean exit", e);
              PowerLoggerService.shouldStop = true;
          }
          log.trace("Value of stop is set to {}", PowerLoggerService.shouldStop);
      }
  
  
      static void main(String [] args) {
          String mode = args[0];
          prefMgr = PreferenceManager.getInstance();
  
          if(null != mode) switch (mode) {
              case "start":
                  PowerLoggerService.shouldStop = false;
                  start(args);
                  log.trace("Exiting the service start method");
                  break;
              case "stop":
                  stop();
                  log.debug("Got request for shutting down service");
                  break;
          }        
      }
  
      public static void logErrorAndStop(String message) {
          notificationServer.publishStatus(MessageType.ERROR,message);
          stop();
      }
  }
  </code></pre>
  
  <p>Gives the follwing trace:</p>
  
  <pre><code>2014-08-07 14:02:27,TRACE,PowerLoggerService,PowerLoggerService.java,101,k.c.p.p.PowerLoggerService,printAllStackTraces
  ==============&gt;Thread reaper-1
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(Unknown Source)
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(Unknown Source)
          at sun.nio.ch.WindowsSelectorImpl.doSelect(Unknown Source)
          at sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source)
          at sun.nio.ch.SelectorImpl.select(Unknown Source)
          at zmq.Poller.run(Poller.java:207)
          at java.lang.Thread.run(Unknown Source)
  ==============&gt;Thread Finalizer
          at java.lang.Object.wait(Native Method)
          at java.lang.ref.ReferenceQueue.remove(Unknown Source)
          at java.lang.ref.ReferenceQueue.remove(Unknown Source)
          at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)
  ==============&gt;Thread iothread-2
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(Unknown Source)
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(Unknown Source)
          at sun.nio.ch.WindowsSelectorImpl.doSelect(Unknown Source)
          at sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source)
          at sun.nio.ch.SelectorImpl.select(Unknown Source)
          at zmq.Poller.run(Poller.java:207)
          at java.lang.Thread.run(Unknown Source)
  ==============&gt;Thread main
          at java.lang.Thread.dumpThreads(Native Method)
          at java.lang.Thread.getAllStackTraces(Unknown Source)
          at kr.co.powermanager.powerlogger.PowerLoggerService.printAllStackTraces(PowerLoggerService.java:89)
          at kr.co.powermanager.powerlogger.PowerLoggerService.start(PowerLoggerService.java:79)
          at kr.co.powermanager.powerlogger.PowerLoggerService.main(PowerLoggerService.java:148)
  ==============&gt;Thread Signal Dispatcher
  ==============&gt;Thread Attach Listener
  ==============&gt;Thread Thread-3
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(Unknown Source)
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(Unknown Source)
          at sun.nio.ch.WindowsSelectorImpl.doSelect(Unknown Source)
          at sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source)
          at sun.nio.ch.SelectorImpl.select(Unknown Source)
          at zmq.Signaler.wait_event(Signaler.java:135)
          at zmq.Mailbox.recv(Mailbox.java:105)
          at zmq.SocketBase.process_commands(SocketBase.java:793)
          at zmq.SocketBase.recv(SocketBase.java:714)
          at org.zeromq.ZMQ$Socket.recv(ZMQ.java:1247)
          at org.zeromq.ZMQ$Socket.recv(ZMQ.java:1235)
          at kr.co.powermanager.powerlogger.LoggerRequestServer.run(LoggerRequestServer.java:45)
  ==============&gt;Thread Thread-4
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.poll(Unknown Source)
          at sun.nio.ch.WindowsSelectorImpl$SubSelector.access$400(Unknown Source)
          at sun.nio.ch.WindowsSelectorImpl.doSelect(Unknown Source)
          at sun.nio.ch.SelectorImpl.lockAndDoSelect(Unknown Source)
          at sun.nio.ch.SelectorImpl.select(Unknown Source)
          at zmq.Signaler.wait_event(Signaler.java:135)
          at zmq.Mailbox.recv(Mailbox.java:105)
          at zmq.Ctx.terminate(Ctx.java:190)
          at org.zeromq.ZMQ$Context.term(ZMQ.java:301)
          at org.zeromq.ZContext.destroy(ZContext.java:98)
          at kr.co.powermanager.powerlogger.PowerLoggerService.stop(PowerLoggerService.java:129)
          at kr.co.powermanager.powerlogger.PowerLoggerService.main(PowerLoggerService.java:152)
  ==============&gt;Thread Reference Handler
          at java.lang.Object.wait(Native Method)
          at java.lang.Object.wait(Unknown Source)
          at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
  
  2014-08-07 14:02:27,TRACE,PowerLoggerService,PowerLoggerService.java,102,k.c.p.p.PowerLoggerService,printAllStackTraces =========================END TRACE
  </code></pre>