standard close behavior



Hi,

I am getting inconsistent behaviors on different systems with the program below. Now, I am wondering if the behavior of this program is triggering unspecified behavior according to SUS.

Can anybody comment, weather closing a file-descriptor should unblock a thread blocked in read(2), when a signal handler uses close(2) on the same file descriptor.

To trigger the behavior in question compile and run the program, and simply signal SIGINT by pressing CTRL-C.

The behavior I am seeing is as follows:
- Linux: continues reading on the file descriptor, and the file descriptor isn't even closed. I.e. read will return valid data, if one hits enter after pressing CTRL-C

- FreeBSD and Solaris: read(2) returns -1 and sets errno to EBADF

I would have suspected the behavior seen by FreeBSD and Solaris. But is that expectation valid, or am I triggering unspecified behavior.

Thanks,
Thomas



#define _REENTRANT 1
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>


void sig_handler(int sig)
{
write(STDOUT_FILENO,"sig_handler\n",12);
close(STDIN_FILENO);
}

void *reader(void *ignored)
{
char buf[4096];
char msg[4096];
int err;

buf[0] = 0;
write(STDOUT_FILENO,"reader started\n",16);
err = read(STDIN_FILENO,buf,sizeof(buf));
if (err == -1)
snprintf(msg,sizeof(msg),"errno = %d, errstr = %s\n",errno,strer
else
snprintf(msg,sizeof(msg),"read = %d, buf = %s\n",err,buf);
write(STDOUT_FILENO,msg,strlen(msg));
return 0;
}

int main(void)
{
pthread_t thr;
int err;
struct sigaction sig;

sig.sa_handler = sig_handler;
err = sigemptyset(&sig.sa_mask);
assert(err == 0);
err = sigaddset(&sig.sa_mask,SIGINT);
assert(err == 0);
sig.sa_flags = SA_RESTART;
err = sigaction(SIGINT,&sig,0);
assert(err == 0);
printf("creating thread...\n");
err = pthread_create(&thr,0,reader,0);
assert(err == 0);
printf("sleeping...\n");
sleep(60);
pthread_join(thr,0);
printf("done...\n");
return 0;
}
.


Quantcast