Dan Sugalski ([EMAIL PROTECTED]) writes:
> At 09:52 AM 4/26/00 -0400, Charles Lane wrote:
> >When Perl opens the socket, it also does (paraphrasing):
>> fp_read = fdopen(socket,"r");
>> fp_write= fdopen(socket,"w");
> >so that you can use stdio routines to read or write from the socket.
> You can't do stdio to sockets on VMS. This bit me a year or so ago. I
> exchanged mail with the C RTL folks, and the net result was "You can't
> fdopen socket file descriptors." It's not in any POSIX standard, so it
> wasn't high on their list of things to fix. (I put in a fix request, but
> this was when they were working on getting the 7.2 changes into the C RTL)
Yeah, I figured that it might come down to that; the tantalizing bit is
that it *almost* works....in fact, were it not for the too-frequent
buffer flushes, it would work in this one case. But for sockets if you
don't flush frequently, you get deadlocks.
If we could make my_fwrite use a "write" call for sockets instead of
"fputs" then we'd be okay, this much is clear.
> >Everything going INTO the fputs routine is fine. But the extra NULs
> >come out the other end.
> That's OK--if you were reading from that socket you'd find that you get
> back what you wrote. Bleah. One ought not print and <> from sockets.
> sysread/syswrite is the way to go.
You read the socket and get back stuff left in the buffer from
previous "accept/fputs/fflush/close" cycles, or NULs or other trash.
That's what the test program demonstrates. Check it out.
I agree that sysread/syswrite are the way to go; but there's a huge
amount of inertia behind using "print", and for good reason.
> >I can see how to do it, but it's really painful....in my_fwrite:
> >
>> if (fstat(fileno(dest),&s) == 0 && S_ISSOCK(s.st_mode)) {
>> write(fileno(dest),src,nitm*itmsz);
>> } else {
>> ...the code currently in my_fwrite...
>> }
> >
> >This works, but that damn "fstat" has to be done for *every* *single*
> >print...that's a performance hit we don't really need. (my_fwrite
> >doesn't know when the FILE * has been closed and reopened, and yes they
> >do get reused).
> Nope. Perl tags each filehandle with a type. We can wedge our own type in
> there for sockets and test for it instead of using fstat. I'll see about
> throwing something together.
If that "nope" was to the reuse, I suggest you run the code in the
debugger. You'll find the same file#'s and FILE* pointers being
reused after closing and reopening a new connection.
As for checking socket/nonsocket, by the time you get down to
"do_print" and "my_fwrite" you're operating on a stdio FILE *, and
have no idea whether the original filehandle was a socket type.
Rewriting most of Perl's i/o code to pass filehandles down to lower
levels didn't seem like a good way to solve a VMS-specific problem.
Other ideas:
1. Subvert FILE:
struct _subvert {
FILE ptr;
int is_a_socket;
};
typedef struct _subvert myFILE;
FILE *fp = fopen(...); or FILE *fp = fdopen(socket,...);
myFILE *fp2 = malloc(sizeof myFILE);
fp2->ptr = *fp;
fp2->is_a_socket = ...;
fp = (FILE *) fp2;
...
(I think this is a *bad* *idea*, and do not advocate it...even IF it works
[big IF])
2. some sort of global file# "is_a_socket" array:
open socket:
int fd = accept(...);
global_isasock[fd] = 1; (dimensioned 256 or the like...)
fp = fdopen(fd...) /* not used for i/o */
...
open file:
FILE * fp = fopen(...);
global_isasock[fileno(fp)] = 0;
close:
global_isasock[fileno(fp)] = 0;
(I suspect this may be as good as we can do...)
--
Drexel University \V --Chuck Lane
----------------->--------*------------<[EMAIL PROTECTED]
(215) 895-1545 / \ Particle Physics [EMAIL PROTECTED]
FAX: (215) 895-5934 /~~~~~~~~~~~ [EMAIL PROTECTED]