|
1 | 1 | /* |
2 | | - * Copyright 2002-2015 the original author or authors. |
| 2 | + * Copyright 2002-2016 the original author or authors. |
3 | 3 | * |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
|
27 | 27 | import java.util.Set; |
28 | 28 | import java.util.concurrent.ConcurrentHashMap; |
29 | 29 | import java.util.concurrent.ScheduledFuture; |
| 30 | +import java.util.concurrent.locks.Lock; |
| 31 | +import java.util.concurrent.locks.ReentrantLock; |
30 | 32 |
|
31 | 33 | import org.apache.commons.logging.Log; |
32 | 34 | import org.apache.commons.logging.LogFactory; |
@@ -106,6 +108,8 @@ private enum State {NEW, OPEN, CLOSED} |
106 | 108 |
|
107 | 109 | private volatile ScheduledFuture<?> heartbeatTask; |
108 | 110 |
|
| 111 | + private final Lock heartbeatLock = new ReentrantLock(); |
| 112 | + |
109 | 113 | private volatile boolean heartbeatDisabled; |
110 | 114 |
|
111 | 115 |
|
@@ -246,8 +250,15 @@ public void disableHeartbeat() { |
246 | 250 |
|
247 | 251 | public void sendHeartbeat() throws SockJsTransportFailureException { |
248 | 252 | if (isActive()) { |
249 | | - writeFrame(SockJsFrame.heartbeatFrame()); |
250 | | - scheduleHeartbeat(); |
| 253 | + if (heartbeatLock.tryLock()) { |
| 254 | + try { |
| 255 | + writeFrame(SockJsFrame.heartbeatFrame()); |
| 256 | + scheduleHeartbeat(); |
| 257 | + } |
| 258 | + finally { |
| 259 | + heartbeatLock.unlock(); |
| 260 | + } |
| 261 | + } |
251 | 262 | } |
252 | 263 | } |
253 | 264 |
|
@@ -282,13 +293,26 @@ protected void cancelHeartbeat() { |
282 | 293 | try { |
283 | 294 | ScheduledFuture<?> task = this.heartbeatTask; |
284 | 295 | this.heartbeatTask = null; |
| 296 | + if (task == null || task.isCancelled()) { |
| 297 | + return; |
| 298 | + } |
285 | 299 |
|
286 | | - if ((task != null) && !task.isDone()) { |
287 | | - if (logger.isTraceEnabled()) { |
288 | | - logger.trace("Cancelling heartbeat in session " + getId()); |
289 | | - } |
290 | | - task.cancel(false); |
| 300 | + if (logger.isTraceEnabled()) { |
| 301 | + logger.trace("Cancelling heartbeat in session " + getId()); |
| 302 | + } |
| 303 | + if (task.cancel(false)) { |
| 304 | + return; |
| 305 | + } |
| 306 | + |
| 307 | + if (logger.isTraceEnabled()) { |
| 308 | + logger.trace("Failed to cancel heartbeat, acquiring heartbeat write lock."); |
| 309 | + } |
| 310 | + this.heartbeatLock.lock(); |
| 311 | + |
| 312 | + if (logger.isTraceEnabled()) { |
| 313 | + logger.trace("Releasing heartbeat lock."); |
291 | 314 | } |
| 315 | + this.heartbeatLock.unlock(); |
292 | 316 | } |
293 | 317 | catch (Throwable ex) { |
294 | 318 | logger.debug("Failure while cancelling heartbeat in session " + getId(), ex); |
|
0 commit comments