22
22
23
23
import java .io .IOException ;
24
24
import java .io .OutputStream ;
25
+ import java .util .concurrent .atomic .AtomicBoolean ;
25
26
26
27
/**
27
28
* {@link OutputStream} for channels. Buffers data upto the remote window's maximum packet size. Data can also be
@@ -36,7 +37,7 @@ public final class ChannelOutputStream extends OutputStream implements ErrorNoti
36
37
private final DataBuffer buffer = new DataBuffer ();
37
38
private final byte [] b = new byte [1 ];
38
39
39
- private boolean closed ;
40
+ private AtomicBoolean closed ;
40
41
private SSHException error ;
41
42
42
43
private final class DataBuffer {
@@ -122,6 +123,7 @@ public ChannelOutputStream(Channel chan, Transport trans, Window.Remote win) {
122
123
this .chan = chan ;
123
124
this .trans = trans ;
124
125
this .win = win ;
126
+ this .closed = new AtomicBoolean (false );
125
127
}
126
128
127
129
@ Override
@@ -151,24 +153,21 @@ public synchronized void notifyError(SSHException error) {
151
153
152
154
private void checkClose () throws SSHException {
153
155
// Check whether either the Stream is closed, or the underlying channel is closed
154
- if (closed || !chan .isOpen ()) {
155
- if (error != null )
156
+ if (closed . get () || !chan .isOpen ()) {
157
+ if (error != null ) {
156
158
throw error ;
157
- else
159
+ } else {
158
160
throw new ConnectionException ("Stream closed" );
161
+ }
159
162
}
160
163
}
161
164
162
165
@ Override
163
166
public synchronized void close () throws IOException {
164
167
// Not closed yet, and underlying channel is open to flush the data to.
165
- if (!closed && chan .isOpen ()) {
166
- try {
167
- buffer .flush (false );
168
- // trans.write(new SSHPacket(Message.CHANNEL_EOF).putUInt32(chan.getRecipient()));
169
- } finally {
170
- closed = true ;
171
- }
168
+ if (!closed .getAndSet (true ) && chan .isOpen ()) {
169
+ buffer .flush (false );
170
+ trans .write (new SSHPacket (Message .CHANNEL_EOF ).putUInt32 (chan .getRecipient ()));
172
171
}
173
172
}
174
173
0 commit comments