RFR: 7152183: TEST_BUG: java/lang/ProcessBuilder/Basic.java failing intermittently [sol]
Martin Buchholz
martinrb at google.com
Mon Oct 8 17:52:58 UTC 2012
Thanks for the changes - this approach looks good. But:
1954 case 0: r = s.read(bytes); break;
1955 case 2: r = s.read(bytes); break;
The two cases are the same code; you want
case 0: r = s.read(); break;
1964 String os = System.getProperty("os.name");
1965 if (os.equalsIgnoreCase("Solaris") ||
1966 os.equalsIgnoreCase("SunOS"))
I wouldn't bother with testing for Solaris explicitly, and just rely on
reflective code testing the implementation of s.
Loop for useCount to go non-negative If and only if we find it reflectively.
1970 if (s.toString().startsWith(
1971
"java.lang.UNIXProcess$DeferredCloseInputStream"))
It's bad style to depend on the output of toString() - better is something
like
Class<?> c = s.getClass();
if (c.getName().equals(...)) {
Oh, now I see the difficulty - the DeferredCloseInputStream may or may not
be wrapped in a BufferedInputStream.
Which makes the reflective code much more annoying.
1976 useCount = (Integer)useCountField.get(s);
I think you want to use getInt (not get) on a field of type int.
1987 while (useCount.intValue() <= 0) {
1988 useCount = (Integer)useCountField.get(s);
1989 Thread.currentThread().yield();
1990 }
I was imagining a loop that looks more like this:
if (useCountField != null) {
while (useCountField.getInt(s) <= 0) {
Thread.currentThread().yield();
}
}
I'm surprised you're not seeing IAE when calling useCountField.get(s) when
wrapped in a BIS. Shouldn't that be a call to useCountField.get(deferred)
instead? Can we fix this in the wrapped case by assigning "s = deferred"?
Thanks,
Martin
On Sun, Oct 7, 2012 at 12:48 PM, Rob McKenna <rob.mckenna at oracle.com> wrote:
> Thanks Martin,
>
> I've uploaded a new webrev to:
>
> http://cr.openjdk.java.net/~robm/7152183/webrev.02/
>
> Let me know if this does the job.
>
>
> -Rob
>
> On 04/10/12 18:24, Martin Buchholz wrote:
>
> Hi all,
>
> Yeah, this particular test is rather racy - sorry about that.
> We need to call p.destroy when the other thread is in the middle of a
> read() system call, and there's no way to know for sure - seeing java
> "read" in the stacktrace is not enough, since it may not have gotten to the
> system call yet.
>
> suggestions:
> pull the computation of the inputstream before the latch to narrow the
> window a bit:
>
> final InputStream s;
> switch (action & 0x1) {
> case 0: s = p.getInputStream(); break;
> case 1: s = p.getErrorStream(); break;
> default: throw
> }
> latch.countdown();
> switch (action & 0x2) {
> case 0: r = s.read(); break;
> case 1: r = s.read(bytes); break;
> }
>
> Examining the stack trace to look for "read" is clever but does not
> actually eliminate the race.
>
> Looking in UNIXProcess.java.solaris I see the use
> of DeferredCloseInputStream. We can eliminate the race on solaris (i.e. if
> the inputstream.getclass isDeferredCloseInputStream) by looping until the
> useCount field of the DeferredCloseInputStream is > 0, using ugly but
> effective reflective code. This should allow us to avoid the horrible
> sleep for 200ms.
>
> You should use yield instead of sleep between loop iterations while
> waiting for the useCount to be bumped.
>
> On other platforms this is not an issue, I think.
>
> Martin
>
> On Thu, Oct 4, 2012 at 12:39 AM, Alan Bateman <Alan.Bateman at oracle.com>wrote:
>
>> On 03/10/2012 22:44, Rob McKenna wrote:
>>
>>> Hi folks,
>>>
>>> The only way I can see this test failing in this manner[*] is if we
>>> destroy the process before we begin the read. That being the case I've
>>> jacked up the sleep (giving the reader thread a little more time to get
>>> cracking) and added a check to see if the threads stack has entered a read
>>> call.
>>>
>>> http://cr.openjdk.java.net/~robm/7152183/webrev.01/ <
>>> http://cr.openjdk.java.net/%7Erobm/7152183/webrev.01/>
>>>
>>> Feedback greatly appreciated.
>>>
>>> -Rob
>>>
>>>
>>> [*] le trace:
>>>
>>> So stack traces are masculine, I didn't know that.
>>
>> I think your analysis is right, it's just that the sleep(10) is not
>> sufficient to ensure that the thread gets to the read method. Increasing
>> the sleep is probably sufficient. The hack to look at the stack trace makes
>> it more robust for really extreme cases, at the cost of potential further
>> maintenance in the event that the implementation changes. In any case it's
>> good to resolve this intermittent test failure.
>>
>> -Alan
>>
>
>
>
More information about the core-libs-dev
mailing list