Skip site navigation (1)Skip section navigation (2)
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>