/**
@file IOerrors.c
@author Mitch Richling@Mee
@Copyright Copyright 1994 by Mitch Richling. All rights reserved.
@brief Example program for UNIX I/O and EINTR handling@EOL
@Keywords UNIX example file I/O EINTR
@Std C89
This C program is intended to illustrate how to handle
the interrupt error (EINTR) returns possible with many
I/O functions. In general an EINTR error is not an
error to exit over, and the I/O operation should be
retried. This code also demonstrates how to handle
write calls that are only partly successful. This kind
of code is not generally required for file I/O, but is
the norm for network programs.
If one is determined to take care of EINTR errors
correctly, then it is best to wrap the I/O functions
inside of user defined functions that take care of the
error conditions in order to reduce the code size and
complexity. I have chosen to take care of the EINTR
errors in-line with no added functions because this
program only calls each I/O function one time!
@Tested
- Solaris 2.8
- MacOS X.2
- Linux (RH 7.3)
*/
#include <sys/stat.h> /* UNIX stat POSIX */
#include <sys/types.h> /* UNIX types POSIX */
#include <sys/uio.h> /* BSD I/O BSD */
#include <stdio.h> /* I/O lib ISOC */
#include <string.h> /* Strings ISOC */
#include <dirent.h> /* UNIX dirs POSIX */
#include <errno.h> /* error stf POSIX */
#include <stdlib.h> /* Standard Lib ISOC */
#include <unistd.h> /* UNIX std stf POSIX */
#include <fcntl.h> /* UNIX file ctrl UNIX */
int main(int argc, char *argv[]);
int main(int argc, char *argv[]) {
int FD;
char *fileName = "foo"; /* The filename we are going to work with. */
int returnValue;
const int maxEINTRers = 10; /* Maximum number interrupt errors to tolerate */
int numEINTRers; /* Counter for number of EINTR errors. */
int numTries; /* Counter for number of write */
const int maxNumTries = 10; /* maximum number of write attempts to finish. */
int numToWrite; /* Number of chars left to write write. */
char buf[255]; /* Buffer to hold data for I/O operations. */
char *writeOffset;
/* First we open the file. */
numEINTRers = 0;
do {
if((FD = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
perror("ERROR: File open");
if(errno != EINTR)
exit(10);
numEINTRers++;
} /* end if */
} while((FD < 0) && (numEINTRers < maxEINTRers));
if(FD < 0) {
errno = EINTR;
perror("ERROR: Repeated errors");
exit(11);
} /* end if */
/* Next we write something to it. Most UNIX systems will always
write the entire request to disk or they will error, but this is
not required behavior so we check for partial writes. In general
this kind of code is only seen in network I/O programs because it
is common to have partial writes in such code. */
numEINTRers = 0;
numTries = 0;
numToWrite = 6;
strcpy(buf, "Hello\n");
writeOffset = buf;
do {
if((returnValue = write(FD, writeOffset, numToWrite - 2)) < 0) {
perror("ERROR: Write error");
if(errno != EINTR)
exit(10);
numEINTRers++;
} else {
printf("Wrote %d of %d bytes", returnValue, numToWrite);
numToWrite = numToWrite - returnValue;
printf(", have %d bytes to go.\n", numToWrite);
if(numToWrite > 0)
writeOffset += returnValue;
numTries++;
numEINTRers = 0; /* Reset so we only exit on maxEINTRers REPEATED errors. */
} /* end else */
} while((numToWrite > 0) && (numTries < maxNumTries) && (numEINTRers < maxEINTRers));
/* Figure out if it worked, and if not print out why. */
if(numToWrite > 0) {
printf("Write failure. Have %d bytes left to write.\n", numToWrite);
if(numTries >= maxNumTries)
printf("Exit because we had too many successful, but incomplete, write attempts.\n");
if(numEINTRers >= maxEINTRers)
printf("Exit because we had too many repeated EINTR errors.\n");
exit(12);
} /* end if */
/* We must close the file to free up system resources. We must
check for errors on the close as well as the other I/O functions.
If the close fails we may not get the last few writes committed
to disk. If we forget to close the file, then it will be closed
for us when our program exits. One should not let the OS close
files because if a problem occurs, the program will never know
and can thus never take action. */
numEINTRers = 0;
do {
if((returnValue = close(FD)) < 0) {
perror("ERROR: File close");
if(errno != EINTR)
exit(13);
numEINTRers++;
} /* end if */
} while((returnValue < 0) && (numEINTRers < maxEINTRers));
if(returnValue < 0) {
errno = EINTR;
perror("ERROR: Repeated errors");
} /* end if */
exit(0);
} /* end func main */
Generated by GNU enscript 1.6.4.