[jcifs] problem with TransactNamedPipeInputStream
sharath reddy
sharathreddy at yahoo.com
Sat Sep 28 01:55:26 EST 2002
Looks good. One question...
Should line 105 be:
105 i = tmp.length - beg_idx;
since tmp now points to the old buffer?
103 tmp = pipe_buf;
104 pipe_buf = new byte[new_size];
105 i = pipe_buf.length - beg_idx;
Same sort of thing as before. i is the length of the
tail fragment. If
the
amount of data in the buffer exceeds that tail
fragment then we
have to
copy the tail and then the head with two separate
arraycopies.
Notice we
*do* subtract i from the total copy amount
unlike the analygous
buggy
operation above.
--- "Michael B. Allen" <miallen at eskimo.com> wrote:
> On Thu, 26 Sep 2002 12:48:06 -0700 (PDT)
> sharath reddy <sharathreddy at yahoo.com> wrote:
>
> >
> > Hi Michael,
> >
> > I was experimenting with some DCE/RPC stuff and I
> ran
> > across the following problem:
> >
> > I'm using named pipes and ran into a problem when
> I do
> > consecutive reads from
> TransactNamedPipeInputStream.
> > Here's what (i think) happens:
> >
> > The first time I read data from the pipe, I
> retrieve
> > 68 bytes of data from the pipe. This sets the
> value
> > of the variables: beg_idx = nxt_idx = 68.
> >
> > The next time data is being written into the pipe
> (via
> > the 'receive' funtion), turns out the buffer is
> too
> > small. So a new, larger buffer is created, and
> the
> > data is copied over from the old buffer into the
> new:
> >
> > System.arraycopy( tmp, beg_idx, pipe_buf, 0, used
> );
> > beg_idx = 0;
> >
> > However, when I do another read from the pipe, I
> seem
> > to have 68 bytes of zeros, then my data. The last
> > 68 bytes of my data is missing.
> >
> > I was able to fix this by adding the following
> line:
> > nxt_idx -= beg_idx;
> >
> > before setting beg_idx to zero, after resizing the
> > buffer.
>
> I have just looked at this more closely. I have
> found two bugs, one of
> which is the one you describe. Just to clarify and
> describe the bugs I'll
> inline the code with little annotations:
>
> 58 public int read( byte[] b, int off, int len )
> throws IOException {
> 59 int result = -1;
> 60 int i;
> 61
> 62 if( len <= 0 ) {
> 63 return 0;
> 64 }
> 65 synchronized( lock ) {
> 66 try {
> 67 while( used == 0 ) {
> 68 lock.wait();
> 69 }
> 70 } catch( InterruptedException ie ) {
> 71 throw new IOException( ie.getMessage()
> );
> 72 }
>
> We've woken up because we've received some data so
> let's copy it into the
> callers buffer. This pipe (like most pipes I
> imagine) is a circular buffer
> so you have two cases; one where all data is in
> one segment and two where
> there's a tail fragment and a beginning
> fragement. Note if there are two
> fragments they have to be on the ends or the data
> would not be continuous.
>
> Apparently i is the length of the tail region.
> The result variable is
> either everything we've got to give or the exact
> length they asked for.
>
> 73 i = pipe_buf.length - beg_idx;
> 74 result = len > used ? used : len;
>
> used is how much data is in the buffer. If there's
> more in the buffer than
> what's the tail then this is the second case so
> we need to copy from the
> tail and then the head fragment with separate
> copys. Unless of course
> result is not that much in which case we can do a
> single copy.
>
> 75 if( used > i && result > i ) {
> 76 System.arraycopy( pipe_buf, beg_idx, b,
> off, i );
> 77 off += i;
>
> Here's a bug. After copy the tail over we proceed
> to copy the full result
> amount. This sound be result - i:
>
> System.arraycopy( pipe_buf, 0, b, off, result
> - i );
>
> and not just result.
>
> 78 System.arraycopy( pipe_buf, 0, b, off,
> result );
> 79 } else {
> 80 System.arraycopy( pipe_buf, beg_idx, b,
> off, result );
> 81 }
>
> We decrement used and increase beg_idx
> accordingly. No need to update
> nxt_idx here. It's the beginning of the free area
> and we have only removed
> data before it (and possibly right up to it
> like you described in your
> scenario).
>
> 82 used -= result;
> 83 beg_idx = ( beg_idx + result ) %
> pipe_buf.length;
> 84 }
> 85 return result;
> 86 }
> 92 int receive( byte[] b, int off, int len ) {
> 93 int i;
>
> This method is called by a different thread when
> there's data to be placed
> into the pipe. Another thread is used because
> the caller is blocked.
> Classic reader/writer problem.
>
> If the len being put in exceeds our buffer increase
> to accomodate.
>
> 94
> 95 if( len > ( pipe_buf.length - used )) {
> 96 byte[] tmp;
> 97 int new_size;
> 98
> 99 new_size = pipe_buf.length * 2;
> 100 if( len > ( new_size - used )) {
> 101 new_size = len + used;
> 102 }
> 103 tmp = pipe_buf;
> 104 pipe_buf = new byte[new_size];
> 105 i = pipe_buf.length - beg_idx;
>
> Same sort of thing as before. i is the length of
> the tail fragment. If the
> amount of data in the buffer exceeds that tail
> fragment then we have to
> copy the tail and then the head with two separate
> arraycopies. Notice we
> *do* subtract i from the total copy amount
> unlike the analygous buggy
> operation above.
>
> 106 if( used > i ) {
> 107 System.arraycopy( tmp, beg_idx,
> pipe_buf, 0, i );
> 108 System.arraycopy( tmp, 0, pipe_buf, i,
> used - i );
>
> Here is the problem. We just reordered the two
> fragments to the beginning
> of the new bigger array. We moved the tail. So if we
> moved the tail we need
> to make nxt_idx point at the end of it. If all the
> data's at the beginning
> of the array now that position is simply:
>
> nxt_idx = used;
>
> 109 } else {
> 110 System.arraycopy( tmp, beg_idx,
> pipe_buf, 0, used );
> 111 }
> 112 beg_idx = 0;
> 114 tmp = null;
> 115 }
> 116
> 117 i = pipe_buf.length - nxt_idx;
> 118 if( len > i ) {
> 119 System.arraycopy( b, off, pipe_buf,
> nxt_idx, i );
> 120 off += i;
> 121 System.arraycopy( b, off, pipe_buf, 0,
> len - i );
> 122 } else {
>
=== message truncated ===
=====
Sharath Reddy
Cell : 512 689 4360
__________________________________________________
Do you Yahoo!?
New DSL Internet Access from SBC & Yahoo!
http://sbc.yahoo.com
More information about the jcifs
mailing list