RFR 8170541: serviceability/jdwp/AllModulesCommandTest.java fails intermittently on Windows and Solaris

David Holmes david.holmes at oracle.com
Tue Feb 27 04:20:05 UTC 2018


The two-step send came in with:

https://bugs.openjdk.java.net/browse/JDK-6401245

"Small JDWP packets with the socket transport causes slow debugging on 
linux 2.6.15 kernel and newer"

David
-----

On 27/02/2018 9:29 AM, serguei.spitsyn at oracle.com wrote:
> On 2/26/18 15:06, Chris Plummer wrote:
>> On 2/26/18 3:00 PM, daniil.x.titov at oracle.com wrote:
>>>
>>>
>>> On 2/26/18 12:16 PM, Chris Plummer wrote:
>>>> On 2/26/18 11:51 AM, daniil.x.titov at oracle.com wrote:
>>>>> Hi David and Sergei,
>>>>>
>>>>> On 2/20/18 10:16 PM, serguei.spitsyn at oracle.com wrote:
>>>>>> Hi David,
>>>>>>
>>>>>>
>>>>>> On 2/20/18 20:02, David Holmes wrote:
>>>>>>> Hi Daniil,
>>>>>>>
>>>>>>> Good find on this!
>>>>>>>
>>>>>>> What does the actual spec say about the length of things and how 
>>>>>>> they may be split across multiple packets? Are we guaranteed that 
>>>>>>> at most two packets will be involved?
>>>>>
>>>>> The JDWP spec 
>>>>> (https://docs.oracle.com/javase/9/docs/specs/jdwp/jdwp-spec.html) 
>>>>> says nothing about splitting JDWP reply packets at all but the 
>>>>> implementation limits the max number of the sent packets to two 
>>>>> packets max. The implementation is dated back to the initial load 
>>>>> that happened in 2007 and the information about the related Jira 
>>>>> issue is missing.
>>>>>
>>>>> open/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c
>>>>>
>>>>> 836    data = packet->type.cmd.data;
>>>>> 837    /* Do one send for short packets, two for longer ones */
>>>>> 838    if (data_len <= MAX_DATA_SIZE) {
>>>>> 839        memcpy(header + JDWP_HEADER_SIZE, data, data_len);
>>>>> 840        if (send_fully(socketFD, (char *)&header, 
>>>>> JDWP_HEADER_SIZE + data_len) !=
>>>>> 841            JDWP_HEADER_SIZE + data_len) {
>>>>> 842            RETURN_IO_ERROR("send failed");
>>>>> 843        }
>>>>> 844    } else {
>>>>> 845        memcpy(header + JDWP_HEADER_SIZE, data, MAX_DATA_SIZE);
>>>>> 846        if (send_fully(socketFD, (char *)&header, 
>>>>> JDWP_HEADER_SIZE + MAX_DATA_SIZE) !=
>>>>> 847            JDWP_HEADER_SIZE + MAX_DATA_SIZE) {
>>>>> 848            RETURN_IO_ERROR("send failed");
>>>>> 849        }
>>>>> 850        /* Send the remaining data bytes right out of the data 
>>>>> area. */
>>>>> 851        if (send_fully(socketFD, (char *)data + MAX_DATA_SIZE,
>>>>> 852                       data_len - MAX_DATA_SIZE) != data_len - 
>>>>> MAX_DATA_SIZE) {
>>>>> 853            RETURN_IO_ERROR("send failed");
>>>>> 854        }
>>>>> 855    }
>>>>>
>>>> Curious. First packet is limited to MAX_DATA_SIZE, 2nd packet has no 
>>>> size limit. What's the point then of splitting it then? Is there a 
>>>> desire to get the header transmitted in a smaller packet.
>>>>
>>>> Chris
>>>
>>> It looks as the goal was to somehow improve the responsiveness in 
>>> case of the large data but I am not sure about this. I could not 
>>> locate any traces in Jira related to this implementation.
>> I was thinking it might be something like that too. Get the header 
>> across the wire quickly. Maybe the user just wants the header (with 
>> size info) initially, and will allocate a large buffer for the rest if 
>> necessary.
> 
> It was my guess too.
> At least, it is the best explanation for this design that looks 
> reasonable to me.
> 
> 
>> Chris
>>> Probably Serguei has some info what is the history behind this design.
> 
> I don't know the history here.
> This was implemented in very early days, most likely, before JDK 1.5 or 
> even 1.4.2.
> 
> Thanks,
> Serguei
> 
>>>>>>>
>>>>>>>  68     protected byte[] readJdwpString(DataInputStream ds) 
>>>>>>> throws IOException {
>>>>>>>   69         byte[] str = null;
>>>>>>>   70         int len = ds.readInt();
>>>>>>>   71         if (len > 0) {
>>>>>>>   72             str = new byte[len];
>>>>>>>   73             ds.read(str, 0, len);
>>>>>>>   74         }
>>>>>>>
>>>>>>> might we get a short-read of the string if it is split across 
>>>>>>> multiple packets?
>>>>>>
>>>>> This and all other reads happen not directly from the socket input 
>>>>> stream but rather from the  DataInputStream object that is 
>>>>> constructed in JdwpReply.initFromStream(InputStream) method. With 
>>>>> the proposed fix we do ensure that the created DataInputStream 
>>>>> object contains data from both packets in cases when the reply was 
>>>>> split in two packets.
>>>>>
>>>>>> Nice catch!
>>>>>> Even though this fix is enough to resolve this problem now, there 
>>>>>> is a chance,
>>>>>> it can fail in the future when more modules are added to the 
>>>>>> platform.
>>>>>>
>>>>>>
>>>>>>> I'm wondering if all these reads should be loops, ensuring we 
>>>>>>> read the expected amount of data.
>>>>>>>
>>>>> Since the implementation of the socket transport limits the max 
>>>>> number of packets the reply might be split in to two packets I 
>>>>> don't think we really need it here.
>>>>>>> One further comment - not sure why we need the print out for when 
>>>>>>> we do read multiple packets?
>>>>>>> That would seem to be a debugging aid.
>>>>>>
>>>>>> Yes, it helps to understand what happens.
>>>>>> Many tests have a lack of tracing which makes it harder to debug 
>>>>>> and understand failures.
>>>>> That is correct.  This additional tracing was added to help to 
>>>>> understand the possible failures in the future.
>>>>>>
>>>>>>
>>>>>> Thanks,
>>>>>> Serguei
>>>>>>
>>>>>>>
>>>>>>> Thanks,
>>>>>>> David
>>>>>>>
>>>>> Thanks,
>>>>> Daniil
>>>>>
>>>>>>> On 21/02/2018 10:14 AM, Daniil Titov wrote:
>>>>>>>> Hi Serguei,
>>>>>>>>
>>>>>>>> A new version of the webrev that has these strings reformatted 
>>>>>>>> is at http://cr.openjdk.java.net/~dtitov/8170541/webrev.02/
>>>>>>>>
>>>>>>>> Thank you!
>>>>>>>>
>>>>>>>> Best regards,
>>>>>>>>
>>>>>>>> Daniil
>>>>>>>>
>>>>>>>> *From: *"serguei.spitsyn at oracle.com" <serguei.spitsyn at oracle.com>
>>>>>>>> *Date: *Tuesday, February 20, 2018 at 3:00 PM
>>>>>>>> *To: *Daniil Titov <daniil.x.titov at oracle.com>, 
>>>>>>>> "serviceability-dev at openjdk.java.net" 
>>>>>>>> <serviceability-dev at openjdk.java.net>
>>>>>>>> *Subject: *Re: RFR 8170541: 
>>>>>>>> serviceability/jdwp/AllModulesCommandTest.java fails 
>>>>>>>> intermittently on Windows and Solaris
>>>>>>>>
>>>>>>>> Hi Daniil,
>>>>>>>>
>>>>>>>> Interesting issue...
>>>>>>>> Thank you for finding to the root cause so quickly!
>>>>>>>>
>>>>>>>> The fix looks good.
>>>>>>>> Could I ask you to reformat these lines to make the L54 shorter ?:
>>>>>>>>
>>>>>>>>    54                 System.out.println("[" + 
>>>>>>>> getClass().getName() + "] Only " + bytesRead + " bytes of " + 
>>>>>>>> dataLength +
>>>>>>>>
>>>>>>>>    55                         " were read in the first packet. 
>>>>>>>> Reading the rest...");
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Serguei
>>>>>>>>
>>>>>>>>
>>>>>>>> On 2/20/18 09:24, Daniil Titov wrote:
>>>>>>>>
>>>>>>>>     Please review the changes that fix intermittent failure of
>>>>>>>>     serviceability/jdwp/AllModulesCommandTest.java test.
>>>>>>>>
>>>>>>>>     The problem here is that for a large data the JDWP agent
>>>>>>>>     (socketTransport_writePacket() method in
>>>>>>>> src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c )
>>>>>>>>     sends 2 packets and in some cases only the first packet is 
>>>>>>>> received
>>>>>>>>     at the time when the test reads the reply from the JDWP 
>>>>>>>> agent. Since
>>>>>>>>     the test does not check that all data is received in the first
>>>>>>>>     packet the correlation between commands and replies became 
>>>>>>>> broken
>>>>>>>>     (the unread second packet is read by the next command and 
>>>>>>>> the reply
>>>>>>>>     for the next command is read by the next after next command 
>>>>>>>> and so on).
>>>>>>>>
>>>>>>>>     Bug: https://bugs.openjdk.java.net/browse/JDK-8170541
>>>>>>>>
>>>>>>>>     Webrev: http://cr.openjdk.java.net/~dtitov/8170541/webrev.01
>>>>>>>>
>>>>>>>>     The tests ran successfully with Mach5.
>>>>>>>>
>>>>>>>>     Best regards,
>>>>>>>>
>>>>>>>>     Daniil
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>
>>
>>
> 


More information about the serviceability-dev mailing list