Alien-uv
view release on metacpan or search on metacpan
libuv/docs/src/guide/processes.rst view on Meta::CPAN
Since we want to pass on an existing descriptor, we'll use ``UV_INHERIT_FD``.
Then we set the ``fd`` to ``stderr``.
.. rubric:: proc-streams/main.c
.. literalinclude:: ../../code/proc-streams/main.c
:linenos:
:lines: 15-17,27-
:emphasize-lines: 6,10,11,12
If you run ``proc-stream`` you'll see that only the line "This is stderr" will
be displayed. Try marking ``stdout`` as being inherited and see the output.
It is dead simple to apply this redirection to streams. By setting ``flags``
to ``UV_INHERIT_STREAM`` and setting ``data.stream`` to the stream in the
parent process, the child process can treat that stream as standard I/O. This
can be used to implement something like CGI_.
.. _CGI: http://en.wikipedia.org/wiki/Common_Gateway_Interface
A sample CGI script/executable is:
.. rubric:: cgi/tick.c
.. literalinclude:: ../../code/cgi/tick.c
The CGI server combines the concepts from this chapter and :doc:`networking` so
that every client is sent ten ticks after which that connection is closed.
.. rubric:: cgi/main.c
.. literalinclude:: ../../code/cgi/main.c
:linenos:
:lines: 49-63
:emphasize-lines: 10
Here we simply accept the TCP connection and pass on the socket (*stream*) to
``invoke_cgi_script``.
.. rubric:: cgi/main.c
.. literalinclude:: ../../code/cgi/main.c
:linenos:
:lines: 16, 25-45
:emphasize-lines: 8-9,18,20
The ``stdout`` of the CGI script is set to the socket so that whatever our tick
script prints, gets sent to the client. By using processes, we can offload the
read/write buffering to the operating system, so in terms of convenience this
is great. Just be warned that creating processes is a costly task.
.. _pipes:
Pipes
-----
libuv's ``uv_pipe_t`` structure is slightly confusing to Unix programmers,
because it immediately conjures up ``|`` and `pipe(7)`_. But ``uv_pipe_t`` is
not related to anonymous pipes, rather it is an IPC mechanism. ``uv_pipe_t``
can be backed by a `Unix Domain Socket`_ or `Windows Named Pipe`_ to allow
multiple processes to communicate. This is discussed below.
.. _pipe(7): http://www.kernel.org/doc/man-pages/online/pages/man7/pipe.7.html
.. _Unix Domain Socket: http://www.kernel.org/doc/man-pages/online/pages/man7/unix.7.html
.. _Windows Named Pipe: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365590(v=vs.85).aspx
Parent-child IPC
++++++++++++++++
A parent and child can have one or two way communication over a pipe created by
settings ``uv_stdio_container_t.flags`` to a bit-wise combination of
``UV_CREATE_PIPE`` and ``UV_READABLE_PIPE`` or ``UV_WRITABLE_PIPE``. The
read/write flag is from the perspective of the child process.
Arbitrary process IPC
+++++++++++++++++++++
Since domain sockets [#]_ can have a well known name and a location in the
file-system they can be used for IPC between unrelated processes. The D-BUS_
system used by open source desktop environments uses domain sockets for event
notification. Various applications can then react when a contact comes online
or new hardware is detected. The MySQL server also runs a domain socket on
which clients can interact with it.
.. _D-BUS: http://www.freedesktop.org/wiki/Software/dbus
When using domain sockets, a client-server pattern is usually followed with the
creator/owner of the socket acting as the server. After the initial setup,
messaging is no different from TCP, so we'll re-use the echo server example.
.. rubric:: pipe-echo-server/main.c
.. literalinclude:: ../../code/pipe-echo-server/main.c
:linenos:
:lines: 70-
:emphasize-lines: 5,10,14
We name the socket ``echo.sock`` which means it will be created in the local
directory. This socket now behaves no different from TCP sockets as far as
the stream API is concerned. You can test this server using `socat`_::
$ socat - /path/to/socket
A client which wants to connect to a domain socket will use::
void uv_pipe_connect(uv_connect_t *req, uv_pipe_t *handle, const char *name, uv_connect_cb cb);
where ``name`` will be ``echo.sock`` or similar. On Unix systems, ``name`` must
point to a valid file (e.g. ``/tmp/echo.sock``). On Windows, ``name`` follows a
``\\?\pipe\echo.sock`` format.
.. _socat: http://www.dest-unreach.org/socat/
Sending file descriptors over pipes
+++++++++++++++++++++++++++++++++++
The cool thing about domain sockets is that file descriptors can be exchanged
between processes by sending them over a domain socket. This allows processes
to hand off their I/O to other processes. Applications include load-balancing
servers, worker processes and other ways to make optimum use of CPU. libuv only
supports sending **TCP sockets or other pipes** over pipes for now.
To demonstrate, we will look at a echo server implementation that hands of
clients to worker processes in a round-robin fashion. This program is a bit
involved, and while only snippets are included in the book, it is recommended
to read the full code to really understand it.
The worker process is quite simple, since the file-descriptor is handed over to
it by the master.
.. rubric:: multi-echo-server/worker.c
.. literalinclude:: ../../code/multi-echo-server/worker.c
:linenos:
:lines: 7-9,81-
:emphasize-lines: 6-8
``queue`` is the pipe connected to the master process on the other end, along
which new file descriptors get sent. It is important to set the ``ipc``
argument of ``uv_pipe_init`` to 1 to indicate this pipe will be used for
inter-process communication! Since the master will write the file handle to the
standard input of the worker, we connect the pipe to ``stdin`` using
``uv_pipe_open``.
.. rubric:: multi-echo-server/worker.c
.. literalinclude:: ../../code/multi-echo-server/worker.c
:linenos:
( run in 2.482 seconds using v1.01-cache-2.11-cpan-e1769b4cff6 )