in sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java [232:311]
public Set<ClientChannelEvent> waitFor(Collection<ClientChannelEvent> mask, long timeout) {
Objects.requireNonNull(mask, "No mask specified");
boolean debugEnabled = log.isDebugEnabled();
boolean traceEnabled = log.isTraceEnabled();
long startTime = System.currentTimeMillis();
/*
* NOTE !!! we must use the futureLock since some of the events that we wait on are related to open/close
* future(s)
*/
synchronized (futureLock) {
long remWait = timeout;
for (Set<ClientChannelEvent> cond = EnumSet.noneOf(ClientChannelEvent.class);; cond.clear()) {
updateCurrentChannelState(cond);
if (debugEnabled) {
if (cond.contains(ClientChannelEvent.EXIT_STATUS)) {
log.debug("waitFor({}) mask={} - exit status={}", this, mask, exitStatusHolder);
}
if (cond.contains(ClientChannelEvent.EXIT_SIGNAL)) {
log.debug("waitFor({}) mask={} - exit signal={}", this, mask, exitSignalHolder);
}
}
boolean nothingInCommon = Collections.disjoint(mask, cond);
if (!nothingInCommon) {
if (traceEnabled) {
log.trace("waitFor({}) call returning mask={}, cond={}", this, mask, cond);
}
return cond;
}
if (timeout > 0L) {
long now = System.currentTimeMillis();
long usedTime = now - startTime;
if ((usedTime >= timeout) || (remWait <= 0L)) {
if (traceEnabled) {
log.trace("waitFor({}) call timeout {}/{} for mask={}: {}",
this, usedTime, timeout, mask, cond);
}
cond.add(ClientChannelEvent.TIMEOUT);
return cond;
}
}
if (traceEnabled) {
log.trace("waitFor({}) waiting {} millis for lock - mask={}, cond={}",
this, remWait, mask, cond);
}
long nanoStart = System.nanoTime();
try {
if (timeout > 0L) {
futureLock.wait(remWait);
} else {
futureLock.wait();
}
long nanoEnd = System.nanoTime();
long nanoDuration = nanoEnd - nanoStart;
if (traceEnabled) {
log.trace("waitFor({}) lock notified on channel after {} nanos", this, nanoDuration);
}
if (timeout > 0L) {
long waitDuration = TimeUnit.MILLISECONDS.convert(nanoDuration, TimeUnit.NANOSECONDS);
if (waitDuration <= 0L) {
waitDuration = 123L;
}
remWait -= waitDuration;
}
} catch (InterruptedException e) {
long nanoEnd = System.nanoTime();
long nanoDuration = nanoEnd - nanoStart;
if (traceEnabled) {
log.trace("waitFor({}) mask={} - ignoring interrupted exception after {} nanos",
this, mask, nanoDuration);
}
}
}
}
}