Source:
<code>public synchronized List<T> shutdown(long timeout) throws InterruptedException { if (this.shutDown) { log.warn("Push manager has already been shut down; shutting down multiple times is harmless, but may " + "indicate a problem elsewhere."); } if (this.shutDownFinished) { final ArrayList<T> unsentNotifications = new ArrayList<T>(); unsentNotifications.addAll(this.retryQueue); unsentNotifications.addAll(this.getQueue()); return unsentNotifications; } if (!this.isStarted()) { throw new IllegalStateException("Push manager has not yet been started and cannot be shut down."); } final Date deadline = timeout > 0 ? new Date(System.currentTimeMillis() + timeout) : null; this.drainingBeforeShutdown = true; this.shutDown = true; while (!this.retryQueue.isEmpty()) { <START> this.connectionPool.waitForEmptyPool(timeout > 0 ? new Date(System.currentTimeMillis() + timeout) : null); <END> if (deadline != null && System.currentTimeMillis() > deadline.getTime()) { break; } } this.drainingBeforeShutdown = false; for (final ApnsConnection<T> connection : this.connectionPool.getAll()) { connection.shutdownGracefully(); } this.connectionPool.waitForEmptyPool(deadline); this.dispatchThread.interrupt(); this.dispatchThread.join(); this.rejectedNotificationListeners.clear(); this.rejectedNotificationExecutorService.shutdown(); if (this.shouldShutDownWorkerGroup) { if (!this.workerGroup.isShutdown()) { final Future<?> workerShutdownFuture = this.workerGroup.shutdownGracefully(); workerShutdownFuture.await(); } } this.shutDownFinished = true; final ArrayList<T> unsentNotifications = new ArrayList<T>(); unsentNotifications.addAll(this.retryQueue); unsentNotifications.addAll(this.getQueue()); return unsentNotifications; }</code><technical_language>stuck if adding pool</technical_language>

Target:
public synchronized List<T> shutdown(long timeout) throws InterruptedException { if (this.shutDown) { log.warn("Push manager has already been shut down; shutting down multiple times is harmless, but may " + "indicate a problem elsewhere."); } if (this.shutDownFinished) { final ArrayList<T> unsentNotifications = new ArrayList<T>(); unsentNotifications.addAll(this.retryQueue); unsentNotifications.addAll(this.getQueue()); return unsentNotifications; } if (!this.isStarted()) { throw new IllegalStateException("Push manager has not yet been started and cannot be shut down."); } final Date deadline = timeout > 0 ? new Date(System.currentTimeMillis() + timeout) : null; this.drainingBeforeShutdown = true; this.shutDown = true; if (this.dispatchThread != null && this.dispatchThread.isAlive()) { this.dispatchThread.interrupt(); } while (!this.retryQueue.isEmpty()) { this.connectionPool.waitForEmptyPool(timeout > 0 ? new Date(System.currentTimeMillis() + timeout) : null); if (deadline != null && System.currentTimeMillis() > deadline.getTime()) { break; } } this.drainingBeforeShutdown = false; for (final ApnsConnection<T> connection : this.connectionPool.getAll()) { connection.shutdownGracefully(); } this.connectionPool.waitForEmptyPool(deadline); this.dispatchThread.interrupt(); this.dispatchThread.join(); this.rejectedNotificationListeners.clear(); this.rejectedNotificationExecutorService.shutdown(); if (this.shouldShutDownWorkerGroup) { if (!this.workerGroup.isShutdown()) { final Future<?> workerShutdownFuture = this.workerGroup.shutdownGracefully(); workerShutdownFuture.await(); } } this.shutDownFinished = true; final ArrayList<T> unsentNotifications = new ArrayList<T>(); unsentNotifications.addAll(this.retryQueue); unsentNotifications.addAll(this.getQueue()); return unsentNotifications; }