about summary refs log tree commit diff
path: root/doc/fifodir.html
blob: b37a2685eb5bc4af01c9ce0b3a7b9f8df031e2f5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Language" content="en" />
    <title>s6: fifodirs</title>
    <meta name="Description" content="s6: fifodirs" />
    <meta name="Keywords" content="s6 instant notification polling fifodir named pipe filesystem" />
    <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
  </head>
<body>

<p>
<a href="index.html">s6</a><br />
<a href="//skarnet.org/software/">Software</a><br />
<a href="//skarnet.org/">skarnet.org</a>
</p>

<h1> Fifodirs </h1>

<p>
 A <em>fifodir</em> is a rendez-vous point between the <em>notifier</em>
of certain events and its <em>listeners</em>. It is implemented via a
directory in the filesystem. No data is stored; it is appropriate to
create fifodirs in a RAM filesystem.
</p>

<h2> Manipulating fifodirs </h2>

<h3> C API </h3>

<h4> For the notifier </h4>

<ul>
 <li> You can create fifodirs via the
<tt>ftrigw_fifodir_create()</tt> function in
<a href="libs6/ftrigw.html">libftrig</a>. </li>
 <li> You can send an event to a fifodir via the
<tt>ftrigw_notify()</tt> function in the notifier part of the
<a href="libs6/ftrigw.html">libftrig</a>. </li>
 <li> You can clean up a fifodir via the
<tt>ftrigw_clean()</tt> function in
<a href="libs6/ftrigw.html">libftrig</a>. </li>
 <li> You can destroy fifodirs via the
<tt>rm_rf()</tt> function in
<a href="//skarnet.org/software/skalibs/libstddjb/djbunix.html">libstddjb</a>. </li>
</ul>

<h4> For a listener </h4>

<ul>
 <li> You can subscribe to a fifodir via the <tt>ftrigr_subscribe()</tt>
function in the listener part of the <a href="libs6/ftrigr.html">libftrig</a>. </li>
 <li> Other functions in the <a href="libs6/ftrigr.html">libftrig</a> allow
you to receive and handle events synchronously or asynchronously. </li>
</ul>

<h3> Unix API </h3>

<h4> For the notifier </h4>

<ul>
 <li> You can create fifodirs with the
<a href="s6-mkfifodir.html">s6-mkfifodir</a> command. </li>
 <li> You can send an event to a fifodir with the
<a href="s6-ftrig-notify.html">s6-ftrig-notify</a> command. </li>
 <li> You can clean up a fifodir with the
<a href="s6-cleanfifodir.html">s6-cleanfifodir</a> command. </li>    
 <li> You can destroy fifodirs with the <tt>rm -rf</tt> command. </li>
</ul>  

<h4> For a listener </h4>

<ul>
 <li> You can subscribe to a fifodir and wait for an event, or a series
or events, with the
<a href="s6-ftrig-wait.html">s6-ftrig-wait</a> command. </li>
 <li> You can subscribe to a fifodir, then trigger a program, then
wait for an event, with the
<a href="s6-ftrig-listen1.html">s6-ftrig-listen1</a> and
<a href="s6-ftrig-listen.html">s6-ftrig-listen</a> commands. This
makes it possible to only send a notification after you're sure
a notifier is actually listening, in order to prevent race conditions. </li>
</ul>
    
<h2> Internals and Unix permissions </h2>

<ul>
 <li> Notifiers and listeners agree on a fifodir. </li>
 <li> The fifodir directory is created by the notifier. It must be writable
by listeners. </li>
 <li> To subscribe, a listener atomically creates a named pipe (FIFO) in this
directory and listens to the reading end. This named pipe must be writable
by the notifier. </li>
 <li> To send an event to listeners, the notifier writes the event byte to
all the named pipes in the directory. Credit for this idea goes to Stefan
Karrmann. </li>
 <li> To unsubscribe, a listener unlinks his named pipe from the directory. </li>
</ul>  

<p>
 Note that in the s6 implementation of fifodirs, there are a few additional
details: for instance, the named pipes created in a fifodir by a listener
follow a strict naming convention, for efficiency and safety reasons. If
you are using fifodirs, it is recommended that you use the provided C library
functions or the <tt>s6-ftrig-*</tt> command line utilities instead of
directly hacking into the fifodir internals.
</p>

<p>
Fifodirs are created by their notifier, so they always originally inherit its
uid and gid. A notifier must be able to make his fifodir either publicly
accessible (anyone can subscribe) or restricted (only a given group can
subscribe).
</p> 

<p>
 A publicly accessible fifodir must have rights 1733:
</p>

<ul>
 <li> Anyone can create a fifo in that fifodir </li>
 <li> Only the notifier can see all the subscribers' fifos </li>
 <li> A listener can only delete its own fifo </li>
 <li> A notifier can delete any fifo for cleaning purposes </li> 
</ul>

<p>
 A restricted fifodir must have the gid <em>g</em> of the group of allowed
listeners and have rights 3730. Unless the notifier is root, it
must be in the group of allowed listeners to be able to create
such a fifodir.
</p>

<ul>
 <li> Only members of <em>g</em> can create a fifo in that fifodir </li>
 <li> Only the notifier can see all the subscribers' fifos </li>
 <li> Fifos are always created with gid <em>g</em> </li>
 <li> A listener can only delete its own fifo </li>
 <li> A notifier can delete any fifo for cleaning purposes </li>
</ul>

<p>
 A named pipe in a fifodir must always belong to its listener and have
rights 0622:
</p>

<ul>
 <li> Only this listener can read on the fifo </li>
 <li> Anyone who has reading rights on the fifodir (i.e. only the notifier)
can write to the fifo </li>
</ul>

<p>
 The <a href="ftrig.html">libftrig</a> interface takes care of all
the subtleties.
</p>

</body>
</html>