Open Bug 278786 Opened 20 years ago Updated 2 years ago

Scriptable inputstream needs not call available in Read

Categories

(Core :: XPCOM, defect)

x86
Linux
defect

Tracking

()

REOPENED
mozilla1.8beta1

People

(Reporter: Biesinger, Unassigned)

References

()

Details

Attachments

(1 file)

Since input streams should deal with a count > their available data, this
Available call is not needed. what's more, it breaks reading files from /proc.
Attached patch patchSplinter Review
Attachment #171587 - Flags: superreview?(darin)
Attachment #171587 - Flags: review?(darin)
Status: NEW → ASSIGNED
Target Milestone: --- → mozilla1.8beta
Comment on attachment 171587 [details] [diff] [review]
patch

r+sr=darin
Attachment #171587 - Flags: superreview?(darin)
Attachment #171587 - Flags: superreview+
Attachment #171587 - Flags: review?(darin)
Attachment #171587 - Flags: review+
so, as a note, the reason this fails for /proc files is that PR_Available is
implemented by seeking to the end of the file and then back, which fails for
proc files...
(http://lxr.mozilla.org/seamonkey/source/nsprpub/pr/src/pthreads/ptio.c#1468)
I wonder why PR_Available isn't implemented using fstat.
since there is no disadvantage in not calling read, I checked this patch in
despite comment 4.

Checking in xpcom/io/nsScriptableInputStream.cpp;
/cvsroot/mozilla/xpcom/io/nsScriptableInputStream.cpp,v  <-- 
nsScriptableInputStream.cpp
new revision: 1.8; previous revision: 1.7
done
Status: ASSIGNED → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
random trivia: this saved 52 bytes of codesize:
  	        -52 (+0/-52)	text (DATA)
  		        -52 (+0/-52)	UNDEF:libxpcom_core.so:text
  			         -2	.nosyms.text
  			        -50	nsScriptableInputStream::Read(unsigned, char**)

(on luna)
So.. some consumers are passing in "-1" as the number of bytes to read.  With
this patch, will we try to allocate PRUint32(-1) bytes?  Or do something else?
> So.. some consumers are passing in "-1" as the number of bytes to read.  With
> this patch, will we try to allocate PRUint32(-1) bytes?  Or do something else?

Actually, you're right.  This patch shouldn't have gone in.  PR_UINT32_MAX is an
acceptable value for the aCount parameter to nsIInputStream::read, and it should
also be an acceptable value for the aCount parameter to
nsIScriptableInputStream::read, as it says:

  "@param aCount [in] the maximum number of bytes to read"

Christian: Back to the drawing board then?  Want to look into fixing
PR_Available instead?  Or, we could "stat" in nsFileInputStream::Available. 
Thoughts?

REOPENING
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
bz: to answer your question.. we'll allocate a 0-length buffer (aCount + 1), but
we'll lie to the underlying stream and tell it the buffer length is aCount bytes
long!
Fun.  ;)

I think the right solution may be that if aCount is more than 4096 or something
we read the stream in a loop in 4096-byte chunks, and realloc the buffer as
needed.....
urg

implementing Available with fstat might be fun, given:
> LANG=C stat /proc/cpuinfo
  File: `/proc/cpuinfo'
  Size: 0               Blocks: 0          IO Block: 1024   regular empty file


An alternative to bz's suggestion might be to call available iff aCount ==
PR_UINT32_MAX... but that kinda sucks, so I'll probably implement someting like
bz's suggestion
It seems bad for PR_Available to be implemented
with seek calls that move the file pointer to
the end of file and back.  If two threads call
PR_Available on the same file descriptor at the
same file, the interleaved seek calls can be
problematic.  I guess it's implemented this way
because fstat returns more information than
PR_Available needs.

Regarding the special files in /proc, I'm
wondering if ioctl(fd, FIONREAD, &bytes)
works.
This would apply to pipes as well.
hmm, yeah... i would expect "ioctl(fd, FIONREAD, &bytes)" to be the right
solution here as well.  biesi: can you give that a try?
nevermind... the proc filesystem seems to return 0 bytes for FIONREAD :(

test prog:

  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/ioctl.h>
  #include <fcntl.h>
                                                                                
  int main(int argc, char **argv)
  {
    int fd, bytes;
                                                                                
    fd = open(argv[1], O_RDONLY);
    if (fd == -1)
      return 1;
                                                                                
    ioctl(fd, FIONREAD, &bytes);
    printf("size: %d\n", bytes);
    return 0;
  }
You should check the return value of ioctl.
Maybe it doesn't work on /proc files.

In any case, we don't seem to have a solution
to make PR_Available work on /proc files.
> You should check the return value of ioctl.
> Maybe it doesn't work on /proc files.

Unfortunately, it returns a success code :(
So... what if I just do:
  aCount = PR_MIN(4096, aCount);
in nsScriptableInputStream::Read? that way the maximum data to read is bounded.
The interface does not guarantee that all data will be read when passing
PR_UINT32_MAX, and in fact for things like sockets and channels, that will not
be the case.

It does break code that assumes passing -1 when reading a file will give the
entire contents. is that a problem?
> It does break code that assumes passing -1 when reading a file will give the
> entire contents. is that a problem?

I think that's ok, but we should verify that consumers like chatzilla and
venkman are still happy.
We use read(-1) in Forecastfox. With this patch it breaks the current versions
of the extension. Its not hard at all to fix it for future versions, but it may
be a pain for all the people using it when they upgrade to Firefox 1.1 or a nightly.
guys, read(-1) will work in firefox 1.1. (in the sense of "will not fail"). do
not worry. it may not read the entire stream though (which was never guaranteed).
biesi: perhaps we should only do the 4096 thing when Available fails?  (if it
turns out that people were depending on read(-1) reading the entire file.)  i'd
rather not resort to this approach, but we should keep it in mind in case we
find that we are breaking several extensions.
fwiw, you will be breaking quite a few exensions. Those who use this[1] js
wrapper or those who copied their code from [2]. I don't know how many
extensions is that break, but I guess quite a few.

[1] http://gratisdei.com/io.js
[2] http://kb.mozillazine.org/Dev_:_Extensions_:_Example_Code_:_File_IO
I backed out the patch for now.
Could we fix that documentation to not give bad advice?  There are plenty of
streams (non-blocking ones, in particular) where that approach would have failed
even before the changes for this bug....
I agree.  Part of whatever patch we come up with here should include
documentation revision to include a warning of that sort.  Also, it is not just
non-blocking streams where this would be a problem.  Indeed, a blocking input
stream returned from nsHttpChannel::Open would have the same problem since it
only blocks until it can return >0 bytes (or error), and there are cases where
Available would not return the full content length (b/c maybe it is not known in
advance -- think transfer-encoding: chunked).
so scriptableinputstream users probably should read until 0 bytes are read
(indicating eof)?

(that's what other streams do; does the scriptable stream follow that?)
(In reply to comment #25)
> Could we fix that documentation to not give bad advice?  There are plenty of
> streams (non-blocking ones, in particular) where that approach would have failed
> even before the changes for this bug....

I'd be interested to see this happen. Does a new bug need to be filed for that?
The documentation in question is not mozilla.org documentation, so if a bug
needs to be filed it needs to be filed with the actual authors of the docs.
Not to ask a stupid question (and this probably is) but ...

I realize that this would have the opposite effect of reducing the size of the
code base, but isn't the obvious solution to use the old code calling Available
for the -1 case and use the new code for other values?  This would not break the
-1 case but still allow read to work for the /proc filesystem which I thought
was what was orginally trying to be solved here.
That would just mean that an attempt to read an entire file from /proc (with -1)
would fail.
(In reply to comment #31)
> That would just mean that an attempt to read an entire file from /proc (with -1)
> would fail.

But that is something that did not work previously, and the original patch,
which caused the regression, left broken as well.  It was just a suggestion.

That's not a good reason to purposefully write code that doesn't work right when
there are several proposals in this bug on how it could work correctly....
QA Contact: xpcom
Assignee: cbiesinger → nobody
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: