Xref: utzoo comp.unix.questions:15596 comp.sys.sequent:349 Path: utzoo!attcan!uunet!ginosko!husc6!ogccse!schaefer From: schaefer@ogccse.ogc.edu (Barton E. Schaefer) Newsgroups: comp.unix.questions,comp.sys.sequent Subject: Turning FNDELAY *off* Message-ID: <4180@ogccse.ogc.edu> Date: 10 Aug 89 23:25:22 GMT Reply-To: schaefer@ogccse.UUCP (Barton E. Schaefer) Organization: Oregon Graduate Center, Beaverton, OR Lines: 86 References: Surely there must be an obvious way to do this, and I'm just missing it. I'm using DYNIX 3.0.12 on a Sequent Symmetry, but my question applies to 4.3 BSD as well, as far as I can tell. I've asked a guru here and come up empty. I have a small program which creates a socket [via socket(2)], binds a name to it [bind(2)], and prepares to receive connections [listen(2)]. I won't go into the details of these calls because they work as expected. (Miraculous, eh?) The program then needs to proceed with another task, checking the socket periodically for connections from a slave program. The master program cannot block when checking for these connections. According to the man page for accept(2): The call returns -1 on error. If it succeeds it returns a non-negative integer which is a descriptor for the accepted socket. The accept will fail if: [EWOULDBLOCK] The socket is marked non-blocking and no connections are present to be accepted. I therefore make the following call, where sd is the descriptor returned by socket(2): if (fcntl(sd, F_SETFL, FNDELAY) < 0) { perror("fcntl"); exit(1); } I note in passing that FNDELAY is defined only for ttys and sockets, but a socket is what I have, so all should be well. I don't get an error return from fcntl(), in any case. The program then goes about its business, periodically doing: if ((ad = accept(sd, sd_name, sd_size)) < 0) { if (errno != EWOULDBLOCK) { perror("accept"); exit(1); } } else { /* talk to slave via ad */ /* much detail omitted */ if (close(ad) < 0) { perror("close"); exit(1); } } This works fine and I am able to connect to the slave through the new descriptor ad. The problem begins when the slave sometimes cannot read data from the socket as quickly as the master tries to write it. The new descriptor ad inherits the FNDELAY attribute from sd, so the master gets an error from write(2) when the socket fills up. So, what I would like to do is turn *off* the FNDELAY attribute of the new descriptor ad and allow the master to do blocking writes. I don't care if this also affects sd, because there is never more than one master-slave connection at a time and I can reset FNDELAY on sd after closing the connection on ad. So the question is Is there any way to restore blocking read/write on a descriptor? I am aware that: It is possible to select(2) a socket for the purposes of doing an accept by selecting it for read. so it is not strictly necessary to do the fcntl() in the first place, and I will convert to use select(2) if necessary. However, it seems odd to me that FNDELAY is a permanent condition. My present interim solution is to note when the error from write() is EWOULDBLOCK, and in that case go to sleep for second and then try the write again. This seems to lose data on rare, nonrepeatable occasions, so a different solution is required. Thanks in advance. -- Bart Schaefer "And if you believe that, you'll believe anything." -- DangerMouse CSNET / Internet schaefer@cse.ogc.edu UUCP ...{sequent,tektronix,verdix}!ogccse!schaefer