harmony-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Tim Ellison <t.p.elli...@gmail.com>
Subject Re: [Fwd: [classlib][NIO|VMI]Interruptible channel implementation - how to interact with Thread?]
Date Fri, 16 Jun 2006 09:31:12 GMT
(switching mail encoding - hopefully nothing lost)

Paulex Yang wrote:
> Archie,
> Thank you for the explanation, I'm appreciated most of your suggestion,
> because mostly I planned to do the same thing as part of interruption
> and asynchronized close implementation. But actually the problem is how
> Thread can understand what the other thread is blocking on. Please see
> my comments inline:
> Archie Cobbs wrote:
>> Paulex Yang wrote:
>>> Jimmy, Jing Lv wrote:
>>>> Archie Cobbs wrote:
>>>>> Paulex Yang wrote:
>>>>>> Seems Thread's implementation must be aware of what operation it
>>>>>> is blocking on. So I propose the following solution:
>>>>> I don't think the VM or java.lang.Thread needs to be involved.
>>>>> First of all, the code performing the blocking operation knows
>>>>> what kind of operation it is, so when it wakes up abnormally it
>>>>> can take the appropriate action. This code doesn't necessarily
>>>>> reside in java.lang.Thread.
>>>>> In Classpath the java.nio stuff is all implemented in native
>>>>> libraries without the VM or java.lang.Thread being specially
>>>>> "aware" of anything. However, classlib's design may be different
>>>>> enough to need it (I haven't studied it as much as you guys).
>>>>> E.g., the java.nio native code does invoke Thread.interrupt() and
>>>>> Thread.interrupted(), but these are normal, API-specified methods.
>>>>> Might be worth taking a look for some design ideas.
>>>> Thanks Archie, it sounds interesting :).
>>>> As I study few about Classpath, I still have a question here. As we
>>>> know, there are three states of "blocking" on a thread. One is
>>>> wait(), sleep() and so forth, thread class handle them itself, it is
>>>> easy to interrupt; and one is blocking on I/O, invoke
>>>> Thread.interrupt() may be not enough as it is blocked on a system
>>>> call, e.g., call read on socket may not return until it receive
>>>> something or it is closed. In this way, the Thread.interrupt should
>>>> know how to close the socket to perform the real interruption. The
>>>> question is: how can the thread know if it is blocked on wait() or
>>>> I/O operation currently? I think this is the reason why Paulex
>>>> require Thread to be involved. So I'm very interested in what does
>>>> Classpath do here to stop I/O operation without get involved?
>>> Actually Thread.interrupt() is required to handle four different
>>> scenario:
>>> 1. wait(), join(), etc, throw InterruptException
>>> 2. blocking I/O, close the channel, and throw ClosedByInterruptException
>>> 3. blocking select, wake up the selector
>>> 4. none of above, just set the thread's interrupt status
>>> So if we don't involve Thread and want to implment scenario 2 and 3,
>>> we may find the situation is:
>>> a. If Thread cannot judge scenario 2/3, so it may think they are both
>>> scenario 4, so Thread.interrupt() just set the interrupt status and
>>> do nothing else, the I/O operation is still blocking there, we cannot
>>> get it actually interrupted.
>>> b. If Thread can find the thread is blocking somewhere, and it
>>> considers all blocking as scenario 1, so the InterruptException is
>>> thrown, but considering scenario c, Selector.select() should be waked
>>> up without exception, while our selector only has the end() executed
>>> in finally block like below, how does end() catch the thrown
>>> InterruptException and handle it silently?
>>> try {
>>>     begin();
>>>     // Perform blocking I/O operation here
>>>     ...
>>> } finally {
>>>     end();
>>> }
>>> c. If Thread can magically find the thread is blocking on I/O or
>>> select, it may need to set the interrupt status, and make the blocked
>>> Java method return with some error, so that the end() can check them.
>>> Further, the Thread needs to know if this blocking I/O is
>>> "interruptible" in Java, for example, the ServerSocket.accept() and
>>> ServerSocketChannel.accept() probably uses same system call, but
>>> Thread should know ServerSocket cannot be interrupted while
>>> ServerSocketChannel can...I have no any idea how Thread can do this
>>> without interaction with NIO channels.
>>> So, Archie, I'm very interested in how Classpath handle this problem.
>>> Would you please help to give more details for it (if no legal concern)?
>> To be honest I'm not sure how exactly it works, or even that it does
>> (I haven't
>> played with the nio stuff at all).. I only know that Thread
>> implementations in
>> Classpath don't have special stuff for NIO channels.
>> Taking a look at Classpath...
>> In Classpath, if select(2) returns EINTR, the select just returns
>> normally
>> (with nothing selected) and then the code checks Thread.interrupted().
>> If set, it closes and throws the exception as necessary.
> Yes I noticed that select(2) on Linux has this good feature, but I
> cannot find similar way on Windows:(.
>> Also, on UNIX at least, one thread may close a file descriptor that
>> another thread is waiting on and the second thread will immediately
>> wake up with an error. So that case is easy to handle.
> Yes, that's what I tried to do in the InterruptAction which is given to
> Thread.setInterruptAction(). The problem here is not *how* to close the
> file descriptor, but is if thread B want to interrupt thread A, the B
> don't know *if* there are any file descriptor to be closed for A or
> *which* file descriptor to close.

Right, because the interruptible channel semantics are indicated by a
Java interface.

> Further, as I mentioned in situation c above, even Thread B can find
> Thread A is blocking on some I/O and can know the file descriptor, I'm
> not sure how it can know *whether* the I/O is interruptible in Java, for
> example, for ServerSocket and ServerSocketChannel which share same fd,
> if you invoke ServerSocketChannel.accept(), it is interruptible, but
> ServerSocket.accept() is not(at least on RI).

I believe that this distinction between regular IO and NIO is
intentional, and we will have to reproduce it.

>> So the only hard part is waking up the sleeping thread that you have
>> interrupted. Once it wakes up, the rest can be handled in Java.
>> A thread blocking on select() will get EINTR if a signal is received.
>> A thread
>> can signal other threads (via native code) using pthread_kill(). So one
>> approach would be for the VM to signal a thread with an otherwise ignored
>> signal when that thread is interrupted. The only possibilities I see are:
>> 1. Interrupt select(2) with a signal
>> 2. select(2) listens on an additional "secret" file descriptor for
>> reading
>>     and the VM writes a byte into it
> This is actually what I did in Harmony-41 for Selector's wakeup()
> method, I open a Pipe and add it to Selector's keys set, write a byte to
> Pipe.SinkeChannel when wake up.
>> 3. select(2) is called with a short timeout, and each time it returns
>>     with timeout we check Thread.interrupted(), then try again.
>> #1 is most efficient and simplest, but requires VM participation (not
>> much).
> I'm afraid #1 may not workable in other platforms in Windows, although
> this is good feature for Linux. And even it works, the issue above still
> exists.
>> #3 has the advantage of being VM indepdendent, but is less efficient.
>> I think for now at least #3 is a viable alternative. A timeout like
>> 250ms would
>> give a quick response time with minimal overhead.

(responding to Archie's comment)
I think option #3 (converting the blocking select call to polling) would
be very noticeable under a heavy load.

> The other problem is we may not have too many freedom to design the
> interruption and Async close implementation, because Java spec requires
> the related operation are encapsulated in AbstractInterruptibleChannel's
> begin()/end() method, which mark the start/end of some interruptible I/O
> operation, so that its subclass can get the capability easily by invoke
> the two methods following spec. And AbstractInterruptibleChannel is
> extensible to classlib users.

I agree, options are limited.



Tim Ellison (t.p.ellison@gmail.com)
IBM Java technology centre, UK.

Terms of use : http://incubator.apache.org/harmony/mailing.html
To unsubscribe, e-mail: harmony-dev-unsubscribe@incubator.apache.org
For additional commands, e-mail: harmony-dev-help@incubator.apache.org

View raw message