1

I have named pipe .\pipe\pipe1 on Windows I want to read from with Java.

From the documentation, FileChannel should be interruptible. Read should throw a ClosedByInterruptException if the reading thread is interrupted from another therad. This probably works for regular files, but I now have a named pipe.

My situation is like this:

RandomAccessFile raf = new RandomAccessFile("\\\\.\\pipe\\pipe1", "r");
FileChannel fileChannel = raf.getChannel();

// later in another thread "readThread"
fileChannel.read(buffer);

// outside the thread reading
readThread.interrupt();

The problem is that the call to interrupt will block and read will remain blocked until something to the named pipe is written so that read will stop blocking.

I need to be able to abort/cancel the read when nothing is written to the pipe while it is not closed yet.

Why does interrupting with the NIO classes not work? Is there a solution to this problem that does not involve busy-waiting or sleep with ready? What would be the best solution for this problem or is there a workaround?

  • If the reader thread does not cooperate by sleeping after reading, it will never interrupt. This has nothing to do with nio. – bichito May 25 '17 at 13:55
  • With NIO classes for sockets, it is possible to write code that does not use sleep, yet reads can be interrupted. My question is, if it is possible to do the same for pipes. Using sleep has a major disadvantage: How long should one sleep before checking for `ready`? If one sleeps too long, messages will be received late, if one sleeps too short, unnecessary CPU cycles are used. What is the best way to solve this problem? Is it impossible? Why can the read not be interrupted, yet with sockets and files it works? – Joseph Dalton May 26 '17 at 09:46
  • I think your problem is the thread not nio. IF the reading thread does not follow this : https://stackoverflow.com/questions/5915156/how-can-i-kill-a-thread-without-using-stop it will **never** interrupt. – bichito May 26 '17 at 13:44
  • No, don't worry, I am using threads properly without interrupts. The problem is the blocking read. But I think there are problems with concurrent reads and writes on pipes anyway, which is a bigger problem, as outlined here: https://stackoverflow.com/questions/4974989/concurrent-read-write-of-named-pipe-in-java-on-windows - so I am working around this with ReentrantLock and doing things a bit differently than planned. – Joseph Dalton May 26 '17 at 13:53
  • Could you post the reading thread code? – bichito May 26 '17 at 13:54
  • No, it's too much and since I asked the question I've moved on to a different approach due to the concurrent read/write problem anyway. But there's not much to replicating it from my example code: Just do the `read` and you will not be able to get out of it. If you manage to cancel the read, then you have won and can answer my question. But if you try to close the `RandomAccessFile`/`FileChannel`, it will also block, and `interrupt` will as well. – Joseph Dalton May 27 '17 at 12:36
  • Ok. I am glad you found another way. There were many issues with your code. So a better design is in order, – bichito May 27 '17 at 12:47
  • What were issues? The code is minimal and I see no problems because it is minimal. I stated what objects I have, what method is blocking and that I try to somehow cancel the blocking method. Could you rewrite it in way that I should have written it? – Joseph Dalton May 27 '17 at 13:10
  • @efekctive You are mistaken. See `java.nio.channels.InterruptibleChannel`. – user207421 May 27 '17 at 15:40
  • https://stackoverflow.com/questions/12315149/interrupt-stop-thread-with-socket-i-o-blocking-operation/12315392#12315392. Googling goes along way – bichito May 27 '17 at 16:02
  • Both your comments are a bit short and not 100% clear to me. @EJP: On what account do you efekctive is mistaken? The "it will never interrupt" part? @efekctive You mean "a long" not "along", right? What point is your link supposed to make? The link is about sockets, and the channels are said to be interruptible in the accepted answer. `InterruptibleChannel` is implemented by `SocketChannel`, which seems to reinforce EJP's comment? Note that my problem is not with threads at all, I don't use stop and I know about the "reinterrupt" pattern in Java; it really is just about the read method. – Joseph Dalton May 28 '17 at 09:08
  • @JosephDalton He is mistaken in his initial claim that `Thread.interrupt()` only interrupts sleep. The existence of the interface I mentioned shows otherwise. `wait()` is another method that can be interrupted. – user207421 May 31 '17 at 17:44

1 Answers1

0

I have not figured out a real solution to the question how to cancel the read. But I needed to adjust anyway and will now explain why. If you have anything to add to the original problem of the blocked read, you can post an additional answer.

A named piped could be treated like a file and opened separately for reading and writing with classic Java IO streams. However, a named piped is often used like a socket and as such, it requires a single file open. So I one could use Java IO streams like this:

RandomAccessFile raf = new RandomAccessFile("\\\\.\\pipe\\pipe1", "rws");
FileChannel fileChannel = raf.getChannel();
InputStream fis = Channels.newInputStream(fileChannel);
OutputStream fos = Channels.newOutputStream(fileChannel);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
PrintWriter pw = new PrintWriter(fos, true);

Now a problem one will later notice is this: If you write while reading, things will get locket up. It seems concurrent reading/writing is not possible, which is outline here.

To solve this, I used a ReentrantLock set to fair to switch from reading/writing. The reading thread is checking readyness and can be triggered with interrupt if one finishes writing and expects a response after this. If ready, the reading buffer is drained. If it is not ready, an interval can be scheduled or simulated for sporadically expected messages. This last part is not optimal, but actually works very well for my use case.

With this, one can build a solution where all threads can be orchestrated to terminate correctly with no blocking and minimal overhead.