Hello people, Here I was writing some code(just for testing purposes) which is supposed to sit and listen to some certain port on machine, and when gets connection, just pass some text file there. (in attached file, apache's access_log file). Originally I was writing this on BSD machine(FreeBSD 2.2.5) and things worked just fine. I brought it to some linux(redhat 4.1 kernel 2.0.29,libc 5.3.*) and weird things happen: When I either compile it with loggin' mode (so file with fd=0 is opened) or run the code with -d switch (so it doesn't close stdin/stdout/stderr at all) things work just fine. (as on BSD), but when I compile it with no LOGGING and DEBUG mode, and run with no -d switch (so all file descriptors are closed). The code hangs up somewhere.(but port isn't listened). I run gdb attach process, and gdb says that code sits in accept function. I wonder if that's just Linux implementation of accept which would want descriptor=0 being opened or something?.. I attached both pieces of code, if anyone would want to play with it. Would be greateful for any hints Fyodor
#include <stdio.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <netinet/in.h> #define LISTEN_PORT 2000 #define SHARE_FILE "/usr/local/etc/httpd/logs/access_log" #define BUFF_SIZE 256 #ifndef LOGGING int fopenlog(void) { close(0); close(1); close(2); return 1; } int flogf(char *str, ... ) { #ifdef DEBUG printf("%s\n",str); #endif return 1; } #else #include "logging.c" #endif int process_connection(int sock_out); int main(int argc, char **argv) { int sock_s,sock_a,sinlen; int debug=0; int portnum=LISTEN_PORT; struct sockaddr_in hostin; if (argc!=1 && !strncmp(argv[1],"-d",2)) { printf("invoked in debugging mode\n"); debug=1; } /* if not debugging, deattach from terminal, start our own session */ if (!debug) { if (fork()) exit(1); // parent exits if(fopenlog()==-1) exit(-1); // if can't open log file setsid(); chdir("/"); umask(0x777); } sock_s=socket(AF_INET,SOCK_STREAM,0); #ifdef DEBUG printf("socket %i created\n",sock_s); #endif if (sock_s<0) { flogf("can't create socket\n"); exit(-1); } bzero((char *)&hostin,sizeof(hostin)); hostin.sin_family=AF_INET; hostin.sin_port=htons(portnum); hostin.sin_addr.s_addr=INADDR_ANY; if (bind(sock_s,(struct sockaddr *)&hostin,sizeof(hostin))<0) { flogf("can't bind socket to %i port\n",portnum); close(sock_s); exit(-1); } #ifdef DEBUG printf("socket %i binded\n",sock_s); #endif if (listen(sock_s,10)<0) { flogf("can't listen to port\n"); close(sock_s); exit(-1); } #ifdef DEBUG printf("socket %i listened\n",sock_s); #endif while(1) { close(sock_a); sinlen=sizeof(hostin); #ifdef DEBUG printf("interation is on\n"); #endif sock_a=accept(sock_s,(struct sockaddr*)&hostin,&sinlen); if (sock_a<0) { flogf("error while accept.Continuing\n"); continue; } switch(fork()) { case -1:continue; case 0: /* child */ process_connection(sock_a); exit(0); } while(waitpid(-1, NULL, (int) NULL) > 0); } } int process_connection(int sock_out) { int sock_in; char buff[BUFF_SIZE]; int count; sock_in=open(SHARE_FILE,O_RDONLY); if (sock_in<0) { flogf("error while opening file\n"); return -1; } while (1) { count=read(sock_in,buff,BUFF_SIZE); if (count<1) break; // eof? count=write(sock_out,buff,count); if (count<1) break; // network connection failed? } close(sock_in); close(sock_out); return 1; }
#define LOG_FILE "server.log" FILE *forlog; int fopenlog(void) { close(0); close(1); close(2); forlog=fopen(LOG_FILE,"wa"); return 1; } int flogf(char *strg, ...) { fprintf(forlog,"[server] %s\n",strg); }