|
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