perlundq/yajsync

broken pipe/deadlock when deferred updates fails

Closed this issue · 0 comments

A deadlock or a broken pipe may occur if Generator tries to notify Sender after Sender and Receiver has agreed to go to the stopped connection state.

Generator will try to notify Sender if any of the deferred attribute updates fails, but Sender is gone and is no longer receiving the messages.

  1. E.g. a broken pipe occurs when doing remote recursive transfers as an unprivileged user and trying to preserve ownership:

    $ yajsync -ro localhost::etc etc.copy

    ...snip...
    WARNING: received I/O error while applying attributes on etc.copy/libvirt/qemu/networks/autostart: etc.copy/libvirt/qemu/networks/autostart: Operation not permitted
    Mar 21, 2016 4:41:12 PM com.github.perlundq.yajsync.ui.YajSyncClient remoteTransfer
    SEVERE: Error: communication closed with peer:
    com.github.perlundq.yajsync.channels.ChannelException: java.io.IOException: Broken pipe
    at com.github.perlundq.yajsync.channels.BufferedOutputChannel.send(BufferedOutputChannel.java:70)
    at com.github.perlundq.yajsync.channels.BufferedOutputChannel.flush(BufferedOutputChannel.java:79)
    at com.github.perlundq.yajsync.channels.TaggedOutputChannel.flush(TaggedOutputChannel.java:78)
    at com.github.perlundq.yajsync.channels.TaggedOutputChannel.putMessage(TaggedOutputChannel.java:55)
    at com.github.perlundq.yajsync.session.Generator$8.process(Generator.java:1014)
    at com.github.perlundq.yajsync.session.Generator$2.process(Generator.java:417)
    at com.github.perlundq.yajsync.session.Generator.processJobQueueBatched(Generator.java:355)
    at com.github.perlundq.yajsync.session.Generator.call(Generator.java:373)
    at com.github.perlundq.yajsync.session.Generator.call(Generator.java:74)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    Caused by: java.io.IOException: Broken pipe
    at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
    at sun.nio.ch.IOUtil.write(IOUtil.java:51)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
    at com.github.perlundq.yajsync.channels.net.StandardSocketChannel.write(StandardSocketChannel.java:62)
    at com.github.perlundq.yajsync.channels.BufferedOutputChannel.send(BufferedOutputChannel.java:60)
    ... 14 more

  2. Likewise, a deadlock may occur if doing the same kind of transfer locally (yajsync -ro /etc etc.copy).
    But: A deadlock does not always occur. And it seems like this also should always result in a broken pipe, but it does not (though it uses Java pipes rather than a tcp socket).