1

I'm communicating between two processes in tcl using Tcl-DP. I create a server using dp_MakeRPCServer on one processs and a client on the other process using dp_MakeRPCClient. When the client is created it connect to the server and a new socket is created between both processes.

First process

dp_MakeRPCServer 50000
file channel
> stdin stdout stderr tcp0

Second process

dp_MakeRPCClient <host> 50000
file channel
> stdin stdout stderr tcp0

First process

file channel
> stdin tcp2 stdout stderr tcp0

We can see that tcp2 on the first process is the socket. Now I'm doing fork and the channels are cloned into the child.

child process (forked from first process)

file channel
stdin tcp2 stdout stderr tcp0

I want to close tcp2 (the socket) on the child without closing the socket between first and second processes.

close tcp2 will just close the socket, in the child, in the first process and in the second process.

I will also accept any other suggestion to do it which consider:

  • At any time other processes may try to connect to the server of the first process. I don't want the child process to receive those calls.
  • At any time the second process may start sending messages to the first process. Again, I don't want the child process to receive those messages.

I should mention that I'm using TclDp 4.0 and tcl 8.4.

Nadav
  • 21
  • 3
  • I'd expect this to work, based on everything (see my answer). Are you sure you're not just talking to the subprocess instead of the parent? That's the sort of silly error I'd make… – Donal Fellows Dec 17 '17 at 11:38
  • I read your answer and it seems to give an answer to my problem except one little problem. It doesn't work :-). I made sure I indeed close tcp2 on the child. Is there anyway to snip the process and see which system call is actually called? – Nadav Dec 18 '17 at 08:49

1 Answers1

0

The following requires you to read the socket FAQ first, but here's the key bit:

Generally the difference between close() and shutdown() is: close() closes the socket id for the process but the connection is still opened if another process shares this socket id. The connection stays opened both for read and write, and sometimes this is very important. shutdown() breaks the connection for all processes sharing the socket id. Those who try to read will detect EOF, and those who try to write will reseive SIGPIPE, possibly delayed while the kernel socket buffer will be filled. Additionally, shutdown() has a second argument which denotes how to close the connection: 0 means to disable further reading, 1 to disable writing and 2 disables both.

On Unix, the Tcl close command on a socket will map to the close() system call on the socket with the standard socket implementation unless you ask for a specific direction to be closed (a Tcl 8.6 feature) in which case the shutdown() system call will be used. This means that with a standard socket, if opened in a parent process prior to a fork, the parent should close the socket after forking. (It's not usually a good idea to have two processes reading from the same TCP socket at once; things get very confused.)

However, TclDP uses its own implementation of socket channels which only supports closing via the close() system call on Unix. (I've not checked on Windows; I don't know the system API very well there.)

That said, I'd expect the close tcp2 in the child process to work provided the parent still has the socket open. In this respect, Tcl really does just expose the capabilities of the operating system. It does not do any special things to make closes in children affect parents.

See Also

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215