\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#301: Split Bidirectional Channels For Half-Close}
\date{December 11, 2006}
\author{Alexandre Ferrieux}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#301}&\textbf{Split Bidirectional Channels For Half-Close}\\\hline
Author&

Alexandre Ferrieux \tipmail{alexandre.ferrieux}{gmail.com}
\\
Created&Monday, \(\text{11}^{\text{th}}\) December 2006\\
Type&Project\\
Tcl Version&\(8.6\)\\
State&Withdrawn\\
Vote&Pending\\
Version&\tipversion$Revision: 1.2 $\\
Post History&\\
Obsoleted By&332\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

This TIP proposes to introduce a \textbf{chan split} command allowing to access both sides of a bidirectional channel (r+ pipe, or socket) as separate Tcl channels, in order to be able to close them separately. This would give Tcl the same level of control that the OS enjoys on the lifetime of such bidirectional connections.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Background}

Bidirectional channels allow Tcl to make an efficient use of a ``filter process'', by exchanging data back and forth over an abstract ``single'' channel.

However, this single channel abstraction comes with a too coarse-grained \textbf{close} primitive. Indeed, it closes both directions simultaneously, while it is often desirable to close ``gracefully'' the half-connection \textit{to} the filter process, leaving the return path open. The effect of such a half-close is that the filter receives a bona fide EOF alone, without a nearly simultaneous SIGPIPE on its write end if it happens to be writing at that time. Moreover, if the filter is itself comprised of a pipeline of processes, some of which doing buffered I/O, then this graceful EOF may be the only way of flushing the chain and receiving back precious data.

This technique is supported by all modern OSes: for pipes there are actually two separate file descriptors/handles, and it suffices to close() the write side; for sockets, a single fd is used, but a specific syscall, shutdown(), brings back the ability to half-close. Hence it is fairly natural for a universal ``OS glove'' like Tcl to expose this universal feature.

\section{Proposed Change}

This TIP proposes to add a \textbf{chan split} subcommand to \textbf{chan}, with the syntax:

\begin{quote}
\textbf{chan split} \textit{channel}
\end{quote}

The \textit{channel} argument indicates the bidirectional channel to be split. The command returns a two element list, with the first element being the name of the channel that is open for reading only, and the second element being the name of the channel that is open for writing only.

After calling [\textbf{chan split} \textit{channel}], \textit{channel} is still opened, but now shares its internal descriptor(s)/handle(s) with the returned readable and writable channel. Then, simple ``reference counting'' at the descriptor level decides when a \textbf{close} translates into an actual close()/shutdown() at the OS level: a descriptor is shut down only when all its Tcl-level representatives have been closed.

As a consequence, the normal idiom for the graceful shutdown described above, is to close the bidirectional channel immediately after splitting it. Later, the sequence is initiated by closing the write side, then waiting for all data and EOF on the read side:
\begingroup\small\begin{verbatim}
foreach {rch wch} [chan split $ch] break
close $ch
...
# initiate graceful shutdown
close $wch
# get back final data
set last [read $rch]
close $rch
\end{verbatim}
\endgroup

In the case of a pipe, the [close \$rch] has the same semantics as [close \$ch] would have had, that is, waiting for the child's exit status, and raising a Tcl exception if nonzero.

\section{Rationale}

I had initially only asked for an extension of \textbf{close}, and Eric Hassold brought up the superbly elegant idea of \textbf{chan split}. Later on, Neil Madden came with the equally beautiful \textbf{chan restrict}, which initially won my preference. Only dirty concern for the amount of work needed vs. actual uses, did make me regard the less ambitious \textbf{chan split} as a more reasonable target (sorry for the change, Neil).

Also, it was suggested that the separation between the read and write side could be exploited not only by \textbf{close}, but also by \textbf{fconfigure}, e.g., to allow for a blocking-read/nonblocking-write, or different baudrates for both directions of a serial port, etc. I feel those are possible later extensions of \textbf{chan split}, however their implementation may be much harder than the \textbf{close} case, because (1) ioctls/fcntl() are not always suited for separation, and (2) multiplexing them is not possible with Threads.

\section{Reference Implementation}

I have not yet written a reference implementation; I assume somebody with a more fluent practice of the channel system implementation will do so more efficiently. However, community feedback on \url{news:comp.lang.tcl} seems to witness some interest in the concept. As a last resort, I can give it a try, of course.

\section{Copyright}

This document has been placed in the public domain.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\end{document}
