Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4154947
Votes 115
Synopsis JDK 1.1.6, 1.2/Windows NT: Interrupting a thread blocked does not unblock IO
Category java:classes_net
Reported Against 1.1.3 , 1.1.4 , 1.1.5 , 1.1.6
Release Fixed
State 11-Closed, Will Not Fix, bug
Priority: 4-Low
Related Bugs 4072256 , 4211692 , 4291378 , 4385444
Submit Date 06-JUL-1998
Description
With JDK 1.1.6, on Solaris, if you interrupt a thread which is blocked
on network IO (specifically, read), the read gets terminated with
InterruptedIOException.   On Windows NT, no such exception is thrown
and the thread is left blocked in the read call.

Attached is a test program to demo the bug.  On Solaris, the output is:
	pause...
	Waiting to accept connections: ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=1234]
	awake...
	Creating connection to server
	Created connection: Socket[addr=localhost/127.0.0.1,port=1234,localport=37294]
	pause...
	Got connection: Socket[addr=localhost/127.0.0.1,port=37294,localport=1234]
	Blocking on read
	awake...
	Interrupting other thread which should be stopped in read
	Interrupt called
	exiting
	PASS: Interrupted as expected
	java.io.InterruptedIOException: operation interrupted
        	at java.net.SocketInputStream.read(SocketInputStream.java:92)
        	at java.net.SocketInputStream.read(SocketInputStream.java:108)
        	at test$1.run(test.java:19)
	gzilla% 


On Windows, the PASS line does not get generated:
	pause...
	Waiting to accept connections: ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=1234]
	awake...
	Creating connection to server
	Created connection: Socket[addr=localhost/127.0.0.1,port=1234,localport=1043]
	pause...
	Got connection: Socket[addr=localhost/127.0.0.1,port=1043,localport=1234]
	Blocking on read
	awake...
	Interrupting other thread which should be stopped in read
	Interrupt called
	exiting

The source of this program is attached.
Work Around
N/A
Evaluation
This is an analysis of the situation provided by   xxxxx@xxxxx   :

The Interrutable IO was and still is the underlying IO semantics
of Java runtime system. However it has never been fully
implemented since JDK1.0.2 because of complexity and
difficulty, especially on win32. Many people have tried to
implemented the Interruptable IO on win32, and no one
had a nice solution. The native win32 IO semantics are
synchonous io and asynchronous io. There is no IO semantics
that is equivalent to interruptable io. So the implementation
of interruptable must use some sort of asynchronous io,
in win32 jargon, use the overlapped io. The overlapped io
is sort of new thing on win32, it was introduced by NT 3.51.
It also supported by Winsock 2. However not all win32 io
system support overlapped io, for example, the stdin,
anonymous pipe, socket connect(), gethostbyname(),
or winsock 1. So if we have to implement the interruptable
io on win32, the only thing we can achieve on both win95
and winnt is to use overlapped (asynchronous) io to simulate
interruptable io for most socket operations, except connect()
and gethostbyname(). Unless Microsoft will introduce new
API in win98 and nt5.

On Solaris, we have green and native package. In green
package, we manage our own IO semantics. With careful
implementation, we could largely implement any semantics
we need. The problem is on native thread. Even the Solaris
API use the interruptable IO semantics, the actual
implementation seems to have some problems. Our current
implementation use the user signal 1 to simulate the
interruptable io behavior. It only barely works. The
SunSoft propose a new API to fully support interruptable io:

  pthread_interrupt_np(pthread_t tid);

(Which implicitly means the current Solaris API does not
fully support interruptable io.) It will be very nice
to have kernel level support. If it is implemented, we
will have near good implementation on Solaris.
porting such a perfectness will be extremely difficult on
other platform.

Even so, there is still no garantee about the state of
IO stream, as I last time talked to Wesley Chen. However
we still have the question: What is semantics of
interruptable io, resumption or termination ???

Similar to the problem of interruptable io, the close(int fd)
semantics is also highly different on win32 and Solaris.
On win32, if a thread blocks on a fd, and second thread
close the fd, the first thread will get an error return
immediately. On Solaris, the second thread will be blocked
until the first thread finishs its io operation. If the io
operation is socket read, both threads may block for a long
time. Now I am trying to implement the win32 close() semantics
on Solaris native thread in a relative expensive way. And
we need to see what the result we get.

In addition to the implementation difficulty, there is also
a usage difficulty. Most win32 programmers don't understand
the interruptable io semantics. On the other side, most unix
developers don't know the close() semantics of win32. And
there are lot of Java code reflecting this. For example,
most Java library (include ours) does not catch
InterruptedException specifically, and treat them as fatal
IOException. It is also true that several Java IO stream
does not implement the close notification semantics (the
win32 close semantics).

Besides the above implementation issues, we also need to
consider the usage of interruptable semantics. Considering
when one user (Java) thread need to wake up another thread,
(let me name it "Foo") which is blocked on the DataInputStream,
which wraps SocketInputStream which wraps recv(). When the
interrupt exception is thrown, the exception will be
propagated all the way up to the user level. However
the state of DataInputStream, SocketInputStream, recv()
are possibly in unknown state. If the user ever want
to resume the io operation later, he may get unknown
data from stream, and get totally lost. So Foo has to
remember to close the stream if he get interrupted.
But in this way, the usability of interruptable is
largely lost. It is much like the close() semantics of
windows. When I use grep to search the entire build
tree, the IOException appear at about 1600 places.
There are 67 places catch IOException, but only 9
places catch InterruptedIOException in PrintStream
and PrintWriter class. Generally, the InterruptedIOException
is considered as IOException, treated as fatal error.
Making InterruptedIOException to have resumption semantics
will be extremely difficult on any platform, and will be
against the semantics of Java language exception. But if we
choose termination semantics, the interruptable io is very
similar to the close() semantics.

On general, even we have a solid implementation now,
we can not expect users to use the semantics correctly, given
the truth most win32 developers background and preference.
Looking at our own VM and core library code, it is obvious
most of our own engineers don't quite understand the issue.

But there is serious backward compatibility issue here.
For now, the Microsoft VM implement the socket interruptable
io in a kludgy way. They use asynchronous select call to
implement it. But that is only work for socket. There is
some overhead with asynchronous socket. (At least the
interrupt will take about 1s to 3s.) In a heavy loaded
socket application, one event polling thread may not be
enough to handle all the network traffice. For long
term, they will probably use overlapped io to implement it.
The latest Netscape VM does not support interruptable socket
io operation.

The above situation has been there for quite long time,
because we don't have a perfect solution on either side.
But the JDK 1.2 is our major release. If we could not
define the Java IO semantics during this release, we will
have more trouble later on. When we really start to implement
them in the future, we will have to face more code break.
Even there is no perfect solution now, we need to face
it and reach an agreement before 1.2 FCS. At least the
users of 1.2 will have a consistent IO semantics to follow.

The situtaion have changed recently on Solaris. For
Solaris 2.7, the close() semantics has been changed to
non-blocking, see Bug 4043763 for details. It will greatly
affect the JVM, because the VM will automatically report
the error code from the OS, which is EBADF in this case.
It is nice for spec to get ready for that now, otherwise
the spec will break on Solaris 2.7. What I suggest is spec
clearly indicates the semantics of stream close(), which
should be, "if a stream is closed by a thread, all other
thread that are blocking on the stream should get an
error return". If there is existing stream implementation
does not meet this semantics, that is a bug. We will try
to fix as much as possible before FCS.

But whether should we deprecate Interruptable IO before
FCS is another big question. If we don't deprecate for 1.2,
we will probably never be able to deprecate it and have to
implement them, either before 1.2 FCS or later? For now
no one really know how to do that on win32.

--

The issue of Thread.interrupt was examined some time ago by
the TRC, see :-
http://javaweb.eng/trc/minutes/99-07-16.txt

The agreement was that the specified functionality cannot be
reasonable implemented and developers should not rely on
interruptable I/O. Even if a solution similiar to Solaris were
implemented on Win32 there would still be inconsistencies on
other OS ports where it would not be possible to provide the
same behaviour.

In merlin the specification for Thread.interrupted has been
updated so that it indicates that an interrupt just sets the 
thread's interrupted status. If the thread is blocked in 
Object.wait it will receive an InterruptException. 

Based on all the above I am closing this bug.

  xxxxx@xxxxx   2001-01-22
Comments
  
  Include a link with my name & email   

Submitted On 26-NOV-1998
bjulien
In my view, this bug is very very important and should be fixed in JDK 1.2. It
has been around for more that a year.


Submitted On 30-NOV-1998
davidholmes
This is obviously a non-trivial problem to get a portable solution for. One
thing that might be considered to ease some situations is to extend the support
for timeouts in I/O operations. At present there is only limited support for
socket accept() and read operations. Using polling loops with timeouts is worse
than being able to interrupt I/O but better than not being able to do anything.
Perhaps a workable compromise can be reached, but in any case this needs to be
spec'ed out much more clearly.


Submitted On 21-DEC-1998
c10819holden
I have just spent three days messing with this to
no avail, before checking the bug parade. If its
in the documentation it MUST work as described 
or be removed. If the behaviour cannot be made
the same across all platform implementations then 
the implications for portable code are (obviously)
serious. 
Polling loops is a workaround (thanks D Holmes)
but I agree with him that its at best a poor
second to the advertised method. 
Note that this interrupt() technique is used
in the multi threaded server example in Java
Examples in a Nutshell. There will be a few 
folk scratching their heads out there over 
this one!!


Submitted On 11-OCT-1999
mjobe
I have implemented a great work around for this.
 I call it the DeterministicInputStream.java.
 This is an InputStream that is given another
 InputStream. It starts a thread to read data
 Into a byte queue. It handle reads by looking
 for data in the byte queue. If none is found,
 it calls wait() until more data is read.
 This ensures that the virtual machine is the
 one doing the blocking rather than the native
 code, from the calling threads perspective,
 allowing the stream to be interrupted via
 the VM. It works great for me...let me know if
 you want it. sirfartalot@home.com


Submitted On 15-NOV-1999
davidholmes
As of September 12 Interruptible IO has been deprecated according to bug
4103109. There are a number of bugs on this issue that are not marked as being
related. They should all now be closed due to the deprecation of Interruptible
IO.
Hopefully the async IO interfaces that are being talked about for future
versions of Java will make this issue moot.


Submitted On 29-DEC-1999
SKuypers
I also experienced this with JDK 1.2.1 on NT


Submitted On 18-FEB-2000
jcb005
I have a similar concern with writes.  I wish to push
data to a client on an essentially permanent connection.
However, I do not want my thread to block forever if the 
client stops reading.  I appear to have no valid options.  
Interruptable IO has been deprecated.
There are no timeouts for writes.
If I read the above correctly, closing the socket from 
another thread will fail under Solaris.


Submitted On 02-MAR-2000
eloisec
Don't deprecate this just because it's hard! It is important feature to have. 
Closed (??) bug 4103109 has suggestion about how to do it in win32...


Submitted On 25-APR-2000
wmskiff
Sun. The comment in your analysis above scares me:

"But the JDK 1.2 is our major release. If we could not 
define the Java IO semantics during this release, we will 
have more trouble later on. When we really start to 
implement them in the future, we will have to face more 
code break. Even there is no perfect solution now, we need 
to face it and reach an agreement before 1.2 FCS. At least 
the users of 1.2 will have a consistent IO semantics to 
follow:"

I suppose this is the last socket/thread related bug that 
hasn't been closed. As far as I can see, these bugs were 
all deprecated or found not to be bugs. Other bug voters 
should duly note that this bug is not about cosmetics. 
A "consistent IO semantics" sounds very good to me.


Submitted On 19-MAY-2000
Pavel
The decision to deprecate interruptable IO at all was not very smart. I hope, this is not final. The 
javax.comm package just begs about interruptable semantics of both serial and parallel port input and 
output. I think the deadlock in defining right semantics happened because too strict implied 
requirements of type "All or nothing". More literally: data being read must be read correctly or 
interrupt must be thrown and stream closed. No third choice. However, please try to apply this vision:
we (hardware guys) are getting incorrect data every time somebody cuts our cables
or closes sight line on InfraRed link. But it does 
not prevent us from reading from the same file again and restoring connection based on higher level
exchange protocol. On no platform (including Windows CE that implements subset of Win32 or 
EPOC32 that has its own port of JVM) we do not rush to close port file just because 
port reported parity error. Who worries? Just re-synchronize with your input stream content
again and continue exchange.

And we even have no that warning in form of IOInterruptedException that our data can be 
transmitted incorrectly. We just have to live with them (and are still alive as everybody can see).

So, what about this relaxed semantics (below is more or less formal specification, as I can understand):

"When thread is blocked for reading or writing gets interrupted, the InterruptedIOException is thrown at 
blocked thread at the earliest convenience. After the exception got catched, the corresponding 
InputStream or OutputStream is still usable and in consistent state whereas the results of the last 
write() or read() operation are not known. That means that the content of buffer passed to read() 
method is undefined and the number and values of bytes received by write() destination are also 
undefined". 

Briefly, just set streams to *any* consistent state (i.e. for InputStreams to be able 
to continue reading and OuputStreams to be able to continue writing) and throw an exception.

What about this? Can you implement this relaxed semantics? If you doubt interruptable IO will 
not be useful in this relaxed form please trust me -- it will be useful! In fact, many of us have
to live with even worse -- and in addition non-portable IO semantics. I am sure all developer who
tries to use Java for communications will applaud you. Timeout controlled IO for InputStreams
and OutputStreams would work also, but it is also not there, right?


Submitted On 04-AUG-2000
faulborn
I agree with Pavel. It would be foolish to abonden interruptable IO. I had the problem, that I needed to 
check for the existance of links from a web index contaning some 50000 URLs. Opening sockets to those 
servers all over the internet caused the JVM to block on a few dozens of URLs for ever since the servers 
stopped replying after a successfully opened socket. I could not interrupt the JVM thread handling those 
connections (neither with interrupt() nor with stop() on NT and Solaris). The solution wich no works fine, is 
to tell a socket to have a defined SO-timeout and SO-linger value. Now the program works fine, since read() 
and close() is interrupted after a defined period of time. Without this "hack" around the problem, I coul have 
given up on using Java for this kind of problem. So think about it: Not implementing at least some 
workaround for this kind of problem is _DEFENITIVELY_ a killer for the Java language itself, since stable 
IO-Connections cannot be programmed if there is no way of interrupting a blocked connection. Afterall, Java 
was invented to have easy IO/ Sockets and is meant to be _THE_ language for the internet. 

By the way, I also find it a stuped idea, that there is currently no way of killing a thread with 100% 
certainty. All operating systems I know of have a way of aborting a thread which has totally crashed (eg. 
kill -9 on UNIX or Taskmanager on NT). However if a thread blocks on IO (at least with sockets), there is no 
way of killing the thread. So how would anyone be able to write an operating system purly in Java? In such 
an operating system, starting a program simply means forking a new thread - if that program fails, there is 
no way of releasing the thread? Think about it!


Submitted On 08-JAN-2001
astrosam
The Evaluation section states that this bug is fixed in the 
author's "merlin workspace", but I don't see the fix 
included in the list of Merlin features (see 
<http://java.sun.com/aboutJava/communityprocess/review/jsr05
9/merlin.pdf>).  Will this fix be included in Merlin (i.e., 
J2SE 1.4)?  Please say yes.


Submitted On 06-FEB-2001
gberche
It would be nice to make the TRC minute available if you 
mention it to justify closing (in fact not fixing) a bug 
which has 180 votes for it!
The URL http://javaweb.eng/trc/minutes/99-07-16.txt that is 
refered to seems to be an URL internal to Sun engineering.


Submitted On 21-SEP-2001
Bebbo
So how is the standard way e.g. in a socket communication, 
to "wake up" a thread wich is a read(byteArray) call, and 
the other side (behavior cannot be changed) waits for a 
close?

It is understandable, that an interruption may leave many 
objects in an inconsistant state, but *at least* an 
interrupt method that acts like close *MUST* be available, 
since workarounds like:

      for (;;) {
        if (is.available() == 0)
        {
          Thread.sleep(50);
          continue;
        }
        int len = is.read(b);
        if (len < 0) 
          break;
        process(b, len);
      }  

are not acceptable (or is that the way of SUN?)

The problem with SUN OS, closing another threads sockets 
will cause long delay for the closing thread, could be 
solved by using a separate thread to perform the close.
For the waiting thread doing read(), it is only important, 
that is interrupted. Even with some delay is ok.

Conclusion: Open this bug again, and fix it!



PLEASE NOTE: JDK6 is formerly known as Project Mustang