@@ -32,6 +32,7 @@ import okio.Buffer
32
32
import okio.BufferedSink
33
33
import okio.BufferedSource
34
34
import okio.Pipe
35
+ import okio.withLock
35
36
import java.io.IOException
36
37
import java.util.concurrent.CountDownLatch
37
38
@@ -181,15 +182,25 @@ internal class PipeRequestBody(
181
182
) : RequestBody() {
182
183
private val pipe = Pipe (pipeMaxBufferSize)
183
184
185
+ /* *
186
+ * Lock used to provide extra synchronization so that fold, write, and
187
+ * close can work correctly in the face of concurrency.
188
+ *
189
+ * See https://github.com/square/okio/issues/1412
190
+ */
191
+ private val pipeLock = pipe.lock
192
+
184
193
/* *
185
194
* Latch that signals when the pipe's sink is closed.
186
195
*/
187
196
private val closed = CountDownLatch (1 )
188
197
189
198
fun write (buffer : Buffer ) {
190
199
try {
191
- pipe.sink.write(buffer, buffer.size)
192
- pipe.sink.flush()
200
+ pipeLock.withLock {
201
+ pipe.sink.write(buffer, buffer.size)
202
+ pipe.sink.flush()
203
+ }
193
204
} catch (e: Throwable ) {
194
205
close()
195
206
throw e
@@ -199,7 +210,9 @@ internal class PipeRequestBody(
199
210
override fun contentType () = contentType
200
211
201
212
override fun writeTo (sink : BufferedSink ) {
202
- pipe.fold(sink)
213
+ pipeLock.withLock {
214
+ pipe.fold(sink)
215
+ }
203
216
if (! duplex) {
204
217
// For non-duplex request bodies, okhttp3
205
218
// expects this method to return only when
@@ -214,7 +227,9 @@ internal class PipeRequestBody(
214
227
215
228
fun close () {
216
229
try {
217
- pipe.sink.close()
230
+ pipeLock.withLock {
231
+ pipe.sink.close()
232
+ }
218
233
} catch (_: Throwable ) {
219
234
// No-op
220
235
} finally {
0 commit comments