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 patch — — Splinter 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: