[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