Re: Tempfile and send_fd()
barries [EMAIL PROTECTED] wrote: On Fri, Nov 17, 2000 at 03:51:35PM +1100, Steve Smith wrote: seek $f, 0, 0; Had a look in Apache::File (below), and it sysopens, so you might want to sysseek(...) instead. Just to clear up one thing: sysopen() doesn't actually belong to the sys* family of functions (syswrite, sysread, sysseek). File handles under perl are buffered by default, whether you open them with perl's open() or with sysopen(). Internally sysopen() does a plain libc open(), but then it follows with a fdopen() call to get a stdio handle anyway. Example (Linux 2.2): $ strace -e trace=open,write,close,nanosleep perl -MFcntl -e 'sysopen(FH, "/tmp/bla", O_WRONLY|O_CREAT); print FH "hey"; sleep 1; print FH "hoy\n"; close FH;' [ ... ] open("/tmp/bla", O_WRONLY|O_CREAT|O_LARGEFILE, 0666) = 3 nanosleep({1, 0}, {1, 0}) = 0 write(3, "heyhoy\n", 7) = 7 close(3)= 0 So the rule of thumb is: use either sysread/syswrite/sysseek, or read//print/seek, but don't mix the two sets on the same filehandle. But you can open your filehandles with open(), sysopen() or any of the OO file packages, as you see fit; both sets of IO functions will work on a filehandle no matter how it was opened. Personally, I don't like the magic parsing in open(), so I tend to use sysopen() always, in combination with the usual read//print/seek. -- Roger Espel Llima, [EMAIL PROTECTED] http://www.iagora.com/~espel/index.html - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Re: Tempfile and send_fd()
On Fri, Nov 17, 2000 at 03:51:03PM +0100, Roger Espel Llima wrote: Internally sysopen() does a plain libc open(), but then it follows with a fdopen() call to get a stdio handle anyway. That explains the results I saw, thanks. - Barrie - To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
Tempfile and send_fd()
Hi, Could somebody tell me why the following testcase doesn't work? use Apache (); use Apache::File (); my $r = Apache-request(); $r-content_type('text/plain'); $r-send_http_header(); my $f = Apache::File-tmpfile(); print $f "test\ntest\n"; $r-send_fd($f); $f-close; All I get is an empty document. My understanding is that the data written to the tmpfile should be available immediately through the filehandle even if it hasn't been flushed. This is running under Registry, on Linux. Thanks, Steve
Re: Tempfile and send_fd()
On Fri, Nov 17, 2000 at 02:42:43PM +1100, Steve Smith wrote: Hi, All I get is an empty document. My understanding is that the data written to the tmpfile should be available immediately through the filehandle even if it hasn't been flushed. I wouldn't bet on it flushing: mod_perl may not have written it out yet. perl often doesn't flush writes to disk until close. Try adding a select( (select( $fh ), $| = 1 )[0] ) ; just after the open and see if that fixes things. Also, Apache doesn't seek or rewind the FD (see below), so even if it's flushed, your file position may no longer be at the beginning of the file, depending on your C RTL. I seem to recall that some require you to seek() between reads and writes to ensure synchronization. That lack of a rewind can be nice when you're caching things: you can sysread some header lines, then turn the rest over to Apache to send. - Barrie API_EXPORT(long) ap_send_fd_length(FILE *f, request_rec *r, long length) { char buf[IOBUFSIZE]; long total_bytes_sent = 0; register int n, w, o, len; if (length == 0) return 0; ap_soft_timeout("send body", r); while (!r-connection-aborted) { if ((length 0) (total_bytes_sent + IOBUFSIZE) length) len = length - total_bytes_sent; else len = IOBUFSIZE; while ((n = fread(buf, sizeof(char), len, f)) 1 ferror(f) errno == EINTR !r-connection-aborted) continue;
Re: Tempfile and send_fd()
On Fri, Nov 17, 2000 at 03:51:35PM +1100, Steve Smith wrote: "Steve" == Steve Smith [EMAIL PROTECTED] writes: Hi, Could somebody tell me why the following testcase doesn't work? snip Nevermind, I got it from the archives eventually : seek $f, 0, 0; Had a look in Apache::File (below), and it sysopens, so you might want to sysseek(...) instead. That seek is flushing the filehandle for you though, here's without the seek (on Linux, YMMV): strace perl -we 'use Fcntl ; sysopen F, "foo", O_RDWR | O_CREAT or die $! ; print F "hi1\n" ; sleep 5 ; print F "hi2\n" ; close F' [snip] open("foo", O_RDWR|O_CREAT|0x8000, 0666) = 3 fcntl(3, F_GETFL) = 0x8002 (flags O_RDWR|0x8000) fstat(3, {st_mode=S_IFCHR|S_ISUID|S_ISGID|0463, st_rdev=makedev(79, 18), ...}) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x400180 00 _llseek(0x3, 0, 0, 0xb67c, 0x1) = 0 fstat(3, {st_mode=S_IFCHR|S_ISUID|S_ISGID|0463, st_rdev=makedev(79, 18), ...}) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 time([974438839]) = 974438839 SYS_175(0, 0xb8d0, 0xb850, 0x8, 0) = 0 SYS_174(0x11, 0, 0xb654, 0x8, 0x11) = 0 SYS_175(0x2, 0xb850, 0, 0x8, 0x2) = 0 nanosleep(0xb7bc, 0xb7bc, 0x401791b4, 0xb7bc, 0xb8d0) = 0 time([974438844]) = 974438844 write(3, "hi1\nhi2\n", 8) = 8 close(3)= 0 and here's with the seek(): strace perl -we 'use Fcntl ; sysopen F, "foo", O_RDWR | O_CREAT or die $! ; print F "hi1\n" ; seek F, 0, 0 ; sleep 5 ; print F "hi2\n" ; close F' open("foo", O_RDWR|O_CREAT|0x8000, 0666) = 3 fcntl(3, F_GETFL) = 0x8002 (flags O_RDWR|0x8000) fstat(3, {st_mode=S_IFCHR|S_ISUID|S_ISGID|0463, st_rdev=makedev(79, 18), ...}) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40018000 _llseek(0x3, 0, 0, 0xb66c, 0x1) = 0 fstat(3, {st_mode=S_IFCHR|S_ISUID|S_ISGID|0463, st_rdev=makedev(79, 18), ...}) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 write(3, "hi1\n", 4)= 4 _llseek(0x3, 0, 0, 0xb788, 0) = 0 time([974438924]) = 974438924 SYS_175(0, 0xb8c0, 0xb840, 0x8, 0) = 0 SYS_174(0x11, 0, 0xb644, 0x8, 0x11) = 0 SYS_175(0x2, 0xb840, 0, 0x8, 0x2) = 0 nanosleep(0xb7ac, 0xb7ac, 0x401791b4, 0xb7ac, 0xb8c0) = 0 time([974438929]) = 974438929 write(3, "hi2\n", 4)= 4 close(3)= 0 Calling syswrite bypasses Perl's buffering, but doesn't address the seek issue: open("foo", O_RDWR|O_CREAT|0x8000, 0666) = 3 fcntl(3, F_GETFL) = 0x8002 (flags O_RDWR|0x8000) fstat(3, {st_mode=S_IFCHR|S_ISUID|S_ISGID|0463, st_rdev=makedev(79, 18), ...}) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40018000 _llseek(0x3, 0, 0, 0xb66c, 0x1) = 0 fstat(3, {st_mode=S_IFCHR|S_ISUID|S_ISGID|0463, st_rdev=makedev(79, 18), ...}) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 write(3, "hi1\n", 4)= 4 time([974439066]) = 974439066 SYS_175(0, 0xb8c0, 0xb840, 0x8, 0) = 0 SYS_174(0x11, 0, 0xb644, 0x8, 0x11) = 0 SYS_175(0x2, 0xb840, 0, 0x8, 0x2) = 0 nanosleep(0xb7ac, 0xb7ac, 0x401791b4, 0xb7ac, 0xb8c0) = 0 time([974439071]) = 974439071 write(3, "hi2\n", 4)= 4 close(3)= 0 - Barrie sub tmpfile { my $class = shift; my $limit = 100; my $r = Apache-request; while($limit--) { my $tmpfile = "$TMPDIR/${$}" . $TMPNAM++; my $fh = $class-new; sysopen($fh, $tmpfile, $Mode, $Perms); $r-register_cleanup(sub { unlink $tmpfile }) if $r; if($fh) { return wantarray ? ($tmpfile,$fh) : $fh; } } }
Re: Tempfile and send_fd()
On Fri, Nov 17, 2000 at 12:32:33AM -0500, barries wrote: On Fri, Nov 17, 2000 at 03:51:35PM +1100, Steve Smith wrote: seek $f, 0, 0; Had a look in Apache::File (below), and it sysopens, so you might want to sysseek(...) instead. No, nevermind, don't: sysseek won't flush the buffer: strace perl -we 'use Fcntl ; sysopen F, "foo", O_RDWR | O_CREAT or die $! ; print F "hi1\n" ; sysseek F, 0, 0 ; sleep 5 ; print F "hi2\n" ; close F' open("foo", O_RDWR|O_CREAT|0x8000, 0666) = 3 fcntl(3, F_GETFL) = 0x8002 (flags O_RDWR|0x8000) fstat(3, {st_mode=S_IFCHR|S_ISUID|S_ISGID|0463, st_rdev=makedev(79, 18), ...}) = 0 mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40018000 _llseek(0x3, 0, 0, 0xb66c, 0x1) = 0 fstat(3, {st_mode=S_IFCHR|S_ISUID|S_ISGID|0463, st_rdev=makedev(79, 18), ...}) = 0 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 _llseek(0x3, 0, 0, 0xb8f8, 0) = 0 time([974439311]) = 974439311 SYS_175(0, 0xb8c0, 0xb840, 0x8, 0) = 0 SYS_174(0x11, 0, 0xb644, 0x8, 0x11) = 0 SYS_175(0x2, 0xb840, 0, 0x8, 0x2) = 0 nanosleep(0xb7ac, 0xb7ac, 0x401791b4, 0xb7ac, 0xb8c0) = 0 time([974439316]) = 974439316 write(3, "hi1\nhi2\n", 8) = 8 close(3)= 0