Dropping a chan in srv via the shell

3 views
Skip to first unread message

Barret Rhoden

unread,
Jun 20, 2019, 11:06:33 AM6/20/19
to akaros-list
I think Ron showed me this a long time ago, and I just finally figured
it out.

My situation: you have a pipe, and a process is listening on one side.
You want to send data into it from the shell. Recall a #pipe has two
files: data and data1. Writes to one file come out the other. It's
bidirectional.

e.g.

$ mkdir pipe
$ /bin/bind \#pipe pipe
$ cd pipe
$ ls
ctl data data1

OK so far. Let's read forever:

$ cat < data1 &
$ ps
1978 cat WAITING 46
$ echo foo > data
foo (that was outputted by cat)
$ ps
(cat is gone)

When echo exited, it closed the FD for data. When one side of a #pipe
closes, the other side is hung up. (More specifically, when *all* FDs
of one side of a pipe closes...). Once they both close, the pipe (which
is mounted in the namespace in this case) can be reused.

You normally don't run into this when dealing with pipes in C programs,
but shells regularly open and close files.

We need something to open the 'data' end of the pipe and never close
the FD. At least not until we want to. Enter #srv. It opens chans and
keeps them open. It also provides a way to share chans, but I don't
actually need that.

Here's the crazy thing I think Ron showed me years ago:

$ echo 0 < data > /srv/foo-pipe

What's the '0'? It's the FD in 'echo' we know will correspond to stdin:
the data file from our #pipe. 'echo' opened data, then wrote the
number of the FD corresponding to it into #srv, which keeps the FD open.

$ echo hi > data
hi (outputted by cat)

$ ps
1978 cat WAITING 46
(cat is still there)

The chan saved in #srv keeps the pipe alive.

We should be able to write into the #srv file too!

$ echo bar > /srv/foo-pipe
echo failed: Bad file number, FD access mode failure: chan mode 0x1,
wanted 0x2 (opened with 0 instead of O_READ?)

Oh well. We can read from it, but something was unhappy when we tried
writing. Thanks to our helpful errstr, the chan's mode was 1. That's
our O_READ. O_WRITE is 2.

Ah, when we "dropped that chan in srv" with echo, we got the file *as
it was opened by echo*: as O_READ for stdin. That's what was shared.
We didn't share a writable file. When we echo'd directly into data,
the file was opened for writing. The only thing I got out of #srv was
keeping *some* FD open - even if it wasn't usable (for writing).

If we wanted to get a writable FD in srv, we can use the same trick as
above, just with a different FD:

$ echo 2 > /srv/foo-writable 2>data

The shell opens data O_WRITE at FD 2, and now we can write to it:

$ echo hi > /srv/foo-writable
hi (cat's output)

And of course we can't read:

$ cat /srv/foo-writable
cat: read error: Bad file number, FD access mode failure: chan mode
0x2, wanted 0x1 (opened with 0 instead of O_READ?)

This was also probably the root of Ron's old trick about running a #ip
connection from the shell:

$ echo 0 < /net/tcp/clone > /srv/my-conv

Which should keep the conversation alive beyond the life of a
particular command in the shell.

Barret

Reply all
Reply to author
Forward
0 new messages