Date: Fri, 1 Dec 2000 01:04:22 +0300 From: Vlad Skvortsov <vss@high.net.ru> To: freebsd-questions@freebsd.org Subject: dup2/pipe issue Message-ID: <20001201010421.A68505@high.net.ru>
next in thread | raw e-mail | index | archive | help
Hello ! My apologize if this is not correct list to ask such questions. I've been debugging my application for over two days for now and cannot dig up what's going on. The application itself is daemon that listens to incoming network connections and then performs fork. The parent continues to listen a socket and if no incoming connections are pending, performs some communications to forked children who serve established connections. So it must use some communication channel with each of its children. When new connection is being accepted server creates two pipes with pipe(2) call and then forks. Parent then closes unused ends of each pipes and returns back to listening network. Child then execs separate application that assumes that stdin/stdout is connected to parent and stderr is connected to client (network socket). So rearrangement of file descriptors should take place. I perform it using the following sequence: /* to_us and from_us are pipes to and from our process, 0th element is read end, 1st - write end. sd is connected socket. */ close (from_us[0]); close (to_us[1]); dup_sock = dup (sd); dup_out = dup (from_us[1]); dup_in = dup (to_us[0]); dup2 (dup_in, 0); dup2 (dup_out, 1); dup2 (dup_sock, 2); /* Child won't need anything except fds 0-2 */ for (i = 3; i < file_descriptors_table_size; i ++) close (i); /* Clear close-on-exec flags for fds 0-2 */ ... /* Exec the app */ ... All dup/dup2 calls are successfull. But when parent tries writing to the pipe it receives SIGPIPE. Debugging shows that the pipe gets widowed after the last dup2 call. Let's see what happens. Up to this points there are following allocations of file descriptors: /* l - socket that daemon listens on a - socket with accepted connection s - syslog socket f[0] - from_us[0] - read end of outgoing pipe f[1] - from_us[1] - write end of outgoing pipe t[0] - to_us[0] - read end of incoming pipe t[1] - to_us[1] - write end of incoming pipe */ l : 0 a : 1 s : 3 f[0]: 5 f[1]: 6 t[0]: 2 t[1]: 4 close (from_us[0]); close (to_us[1]); l : 0 a : 1 s : 3 f[1]: 6 t[0]: 2 dup_sock = dup (sd); l : 0 a : 1 4 s : 3 f[1]: 6 t[0]: 2 dup_out = dup (from_us[1]); l : 0 a : 1 4 s : 3 f[1]: 6 5 t[0]: 2 dup_in = dup (to_us[0]); l : 0 a : 1 4 s : 3 f[1]: 6 5 t[0]: 2 7 dup2 (dup_in, 0); a : 1 4 s : 3 f[1]: 6 5 t[0]: 2 7 0 dup2 (dup_out, 1); /* (1) */ a : 4 s : 3 f[1]: 6 5 1 t[0]: 2 7 0 /* The pipe is still functioning here (all FDs: 0, 2 and 7) */ dup2 (dup_sock, 2); /* (2) */ a : 4 2 s : 3 f[1]: 6 5 1 /* outgoing pipe */ t[0]: 7 0 /* incoming pipe */ /* The pipe appears to be broken after this call (neither FD 0, nor 7) */ Two things to mention here. The outgoing pipe is okay. The only difference in setting up FD1 and FD0 is that when setting up outgoing pipe (FD1) no dup2 calls freed any of FDs associated with pipe. On the other side when setting up incoming pipe, dup2 call marked as (2) freed descriptor 2 associated with this pipe and has broken the pipe down. Closing any descriptors associated with pipe using close(2) call doesn't break pipe. The second thing is that dup2 doesn't break _socket_ even freeing descriptor associated with it (dup2 call marked as (1)). Can anyone point me to the direction how to debug/solve the problem ? -- Vlad Skvortsov, vss@ulstu.ru, vss@high.net.ru To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-questions" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001201010421.A68505>