2004-11-15 23:29:39

by Prasanna Meda

[permalink] [raw]
Subject: accept behaviour on EMFILE/ENFILE

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <unistd.h>
/* <[email protected]> */

int *diskfds;
int maxdiskfd;
int curdiskfd;
int cfd, sfd, nfd;

void pexit(const char *msg)
{
perror(msg);
close(sfd);
close(cfd);
close(nfd);
printf("TEST FAILED\n");
exit(1);
}

int main(int argc, char *argv[])
{
struct sockaddr_in myaddr, servaddr, cliaddr;
int len = sizeof(struct sockaddr_in), yes = 1;
unsigned short sport;
int *olddiskfds;

if (argc < 2) {
printf("Usage:%s port\n", argv[0]);
exit(1);
}
sport = atoi(argv[1]);

/* Setup connection */
cfd = socket(PF_INET, SOCK_STREAM, 0);
sfd = socket(PF_INET, SOCK_STREAM, 0);
if (cfd < 0 || sfd < 0)
pexit("socket");
memset((void *)&myaddr, sizeof(myaddr), 0);
memset((void *)&servaddr, sizeof(myaddr), 0);
memset((void *)&cliaddr, sizeof(myaddr), 0);
myaddr.sin_port = servaddr.sin_port = htons(sport);
myaddr.sin_family = servaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_addr.s_addr = 0;

if (bind(sfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0)
pexit("bind");
if (setsockopt(sfd, SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) < 0)
perror("setsockopt");
if (listen(sfd, 10) < 0)
pexit("listen");
if (fcntl(sfd, F_SETFL, O_NONBLOCK) < 0)
perror("fnctl");
if (connect(cfd, (struct sockaddr *)&servaddr, len) < 0)
pexit("connect");
printf("Client connected to server!\n");

/* consume fds */
while (1) {
if (curdiskfd == maxdiskfd) {
maxdiskfd = (!maxdiskfd)?1:(maxdiskfd<<1);
olddiskfds = diskfds;
if (!(diskfds = (int *)malloc(sizeof(int)*maxdiskfd)))
pexit("malloc");
memcpy(diskfds, olddiskfds, (maxdiskfd >> 1));
free(olddiskfds);
}
if ((diskfds[curdiskfd] = open("/dev/null", O_RDONLY)) < 0) {
printf("Server opened %d diks fds!\n", curdiskfd);
break;
}
curdiskfd++;
}

nfd = accept(sfd, (struct sockaddr *)&cliaddr, &len);
if (nfd < 0) {
perror("1st accept");
close(diskfds[--curdiskfd]);
nfd = accept(sfd, (struct sockaddr *)&cliaddr, &len);
if (nfd < 0)
pexit("2nd accept");
}
printf("Server got connection from %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
printf("TEST PASSED\n");
return (0);
}



Attachments:
acceptonmaxfd.c (2.32 kB)