summaryrefslogtreecommitdiff
path: root/ReadMe.html
blob: 686eee6d7108d3f41d14e242a32013c0379a4d05 (plain)
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

<html>

<head>
	<meta name="author" content="Philip Semanchuk">
	<meta name="copyright" content="All contents &copy; 2014 Philip Semanchuk">
	<meta name="keywords" content="python sysv system v ipc semaphore shared memory">

    <title>System V IPC for Python - Semaphores, Shared Memory and Message Queues</title>

    <style type="text/css">
        dt {
            font-family: monospace;
            font-weight: bold;
            padding-bottom: .33em;
            margin-top: 1em;
        }
        span[lang] { font-style: italic; }

        span.param {
            font-family: monospace;
            font-style: italic;
        }

        span.book_title {
        	text-decoration: underline;
        }

        pre { margin-left: 2em; }

        li { margin-top: 1em; margin-bottom: 1em; }

        form {
            width: 20em;
            float: right;
            font-size: 90%;
            margin-left: 1em;
            margin-bottom: 1em;
            float: right;
        }
        fieldset, legend {
            background-color: #d0d0a9;
        }
        /* This style is only present on the local version of the readme.
           In the online version, the RSS feed is displayed. */
        div.rss { display: none; }
    </style>
</head>

<body>

<h2>System V IPC for Python - Semaphores, Shared Memory and Message Queues</h2>

<div class="rss">
    <a href="rss.xml"><img src="/common/images/rss.png" width="28" height="28" alt=""></a>
    <br><a href="rss.xml">RSS</a>
</div>

<p>This describes the <tt>sysv_ipc</tt> module which gives Python access
to System V inter-process semaphores, shared memory and message queues
on most (all?) *nix flavors. Examples include OS X, Linux, FreeBSD,
OpenSolaris 2008.11,
and <a href="http://f-utility.tumblr.com/post/525726296/compiling-sysv-ipc-python-module-with-gcc-on-aix-5-2">AIX 5.2</a>.
It might also work under Windows with a library like
<a href="http://www.cygwin.com/">Cygwin</a>.
</p>

<p>It works with Python 2.4 &ndash; 3.x.
It's released
under a <a href="http://creativecommons.org/licenses/BSD/">BSD license</a>.
</p>

<p>You can <strong>download
<a href="sysv_ipc-0.6.8.tar.gz">sysv_ipc version 0.6.8</a>
</strong>
(<a href="sysv_ipc-0.6.8.md5.txt">[md5 sum]</a>,
<a href="sysv_ipc-0.6.8.sha1.txt">[sha1 sum]</a>)

which contains the source code, setup.py, installation instructions and
<a href="#samples">sample code</a>. You can read about
<a href="#current">all of the changes in this version</a>.
</p>

<p>
You might also want to read
about some <a href="#bugs">known bugs</a>.
</p>

<p>You might be interested in the very similar module
<a href="/philip/posix_ipc/"><tt>posix_ipc</tt></a>
which provides Python access to POSIX IPC primitives. POSIX IPC is a little
easier to use than SysV IPC, but not all operating systems support it
completely.
</p>

<h2>Module <tt>sysv_ipc</tt></h2>

<p>Jump to <a href="#semaphore">semaphores</a>,
<a href="#shared_memory">shared memory</a>, or
<a href="#message_queue">message queues</a>.</p>


<h3>Module Functions</h3>

<dl>
    <dt>attach(id, [address = None, [flags = 0]])</dt>
    <dd>Attaches the (existing) shared memory that has the given <tt>id</tt> and
    	returns a new SharedMemory object. See
    	<a href="#attach">SharedMemory.attach()</a> for details on the
    	<tt>address</tt> and <tt>flags</tt> parameters.

    <p>This method is useful only under fairly unusual circumstances.
    	You probably don't need it.
    </p>
    </dd>

    <dt>ftok(path, id, [silence_warning = False])</dt>
    <dd>Calls <tt>ftok(path, id)</tt>. Note that
    <a href="#ftok_weakness"><tt>ftok()</tt> has limitations</a>, and this
    function will issue a warning to that effect unless
    <tt>silence_warning</tt> is True.
    </dd>

    <dt>remove_semaphore(id)</dt>
    <dd>Removes the semaphore with the given <tt>id</tt>.</dd>

    <dt>remove_shared_memory(id)</dt>
    <dd>Removes the shared memory with the given <tt>id</tt>.</dd>

    <dt>remove_message_queue(id)</dt>
    <dd>Removes the message queue with the given <tt>id</tt>.</dd>
</dl>


<h3>Module Constants</h3>

<dl>
    <dt>IPC_CREAT, IPC_EXCL and IPC_CREX</dt>
    <dd><tt>IPC_CREAT</tt> and <tt>IPC_EXCL</tt> are flags used when
        creating IPC objects. They're
        bitwise unique and can be ORed together. <tt>IPC_CREX</tt> is
        shorthand for <tt>IPC_CREAT | IPC_EXCL</tt>.

        <p>When passed to an IPC object's constructor, <tt>IPC_CREAT</tt> indicates
            that you want to create a new object or open an existing one. If you want
            the call to fail if an object with that key already exists, specify
            the  <tt>IPC_EXCL</tt> flag, too.
        </p>
    </dd>

    <dt>IPC_PRIVATE</dt>
    <dd>This is a special value that can be passed in place of a key. It implies that
        the IPC object should be available only to the creating process or its
        child processes (e.g. those created with <tt>fork()</tt>).
    </dd>

    <dt>KEY_MIN and KEY_MAX</dt>
    <dd>Denote the range of keys that this module accepts. Your OS might
        limit keys to a smaller range depending on the typedef of
        <tt>key_t</tt>.

        <p>Keys randomly generated by this module are in the range
        	<tt>1 &lte; key &lte; SHRT_MAX</tt>.
           That's type-safe unless your OS has a very bizarre
           definition of <tt>key_t</tt>.
        </p>
    </dd>

    <dt>SEMAPHORE_VALUE_MAX</dt>
    <dd>The maximum value of a semaphore.
    </dd>

    <dt>PAGE_SIZE</dt>
    <dd>The operating system's memory page size, in bytes. It's probably a good
        idea to make shared memory segments some multiple of this size.
    </dd>

    <dt>SEMAPHORE_TIMEOUT_SUPPORTED</dt>
    <dd>True if the platform supports timed semaphore waits, False otherwise.</dd>

    <dt>SHM_RND</dt>
    <dd>You probably don't need this, but it can be used when attaching shared
        memory to force the address to be
        rounded down to SHMLBA. See your system's man page for <tt>shmat()</tt>
        for more information.
    </dd>

    <dt>SHM_HUGETLB, SHM_NORESERVE and SHM_REMAP</dt>
    <dd>You probably don't need these. They're Linux-specific flags that can
        be passed to the SharedMemory
        constructor, or to the <tt>.attach()</tt> function in the case of
        SHM_REMAP. See your system's man page for <tt>shmget()</tt>
        and <tt>shmat()</tt> for more information.
    </dd>
</dl>

<h3>Module Errors</h3>

<p>In addition to standard Python errors (e.g. <tt>ValueError</tt>),
this module raises custom errors. These errors cover
situations specific to IPC.
</p>

<dl>
    <dt>Error</dt>
    <dd>The base error class for all the custom errors in this module. This
        error is occasionally raised on its own but you'll almost
        always see a more specific error.
    </dd>

    <dt>InternalError</dt>
    <dd>Indicates that something has gone very wrong in the module code. Please
        report this to the maintainer.
    </dd>

    <dt>PermissionsError</dt>
    <dd>Indicates that you've attempted something that the permissions on the
        IPC object don't allow.
    </dd>

    <dt>ExistentialError</dt>
    <dd>Indicates an error related to the existence or non-existence of
        an IPC object.
    </dd>

    <dt>BusyError</dt>
    <dd>Raised when a semaphore call to <tt>.P()</tt> or <tt>.Z()</tt> either times out
        or would be forced to wait when its <tt>block</tt> attribute is False.
    </dd>

    <dt>NotAttachedError</dt>
    <dd>Raised when a process attempts to read from or write to a shared memory
        segment to which it is not attached.
    </dd>
</dl>


<h3 id="semaphore">The Semaphore Class</h3>

<p>This is a handle to a semaphore.</p>

<h4>Methods</h4>

<dl>
    <dt>Semaphore(key, [flags = 0, [mode = 0600, [initial_value = 0]]])</dt>
    <dd>Creates a new semaphore or opens an existing one.

        <p><span class="param">key</span> must be <tt>None</tt>,
            <tt>IPC_PRIVATE</tt> or
        an integer &gt; <tt>KEY_MIN</tt> and &le; <tt>KEY_MAX</tt>. If the key
        is <tt>None</tt>, the module chooses a random unused key.
        </p>

        <p>The <span class="param">flags</span> specify whether you want to create a
            new semaphore or open an existing one.
        </p>

        <ul>
            <li>With <span class="param">flags</span> set to the <strong>default</strong> of <tt>0</tt>, the module attempts
                to <strong>open an existing</strong> semaphore identified by <span class="param">key</span> and raises
                a <tt>ExistentialError</tt> if that semaphore doesn't exist.
            </li>

            <li>With <span class="param">flags</span> set to <tt>IPC_CREAT</tt>, the module
                <strong>opens</strong> the semaphore identified by
                <span class="param">key</span> <strong>or creates</strong> a new
                one if no such semaphore exists. Using <tt>IPC_CREAT</tt> by itself
                is not recommended. (See <a href="#sem_init">Semaphore Initialization</a>.)
            </li>

            <li>With <span class="param">flags</span> set to
                <tt>IPC_CREX</tt> (<tt>IPC_CREAT | IPC_EXCL</tt>),
                the module
                <strong>creates a new semaphore</strong> identified by <span class="param">key</span>. If a
                semaphore with that key already exists, the call raises an
                <tt>ExistentialError</tt>.
                <strong>The <span class="param">initial_value</span> is ignored unless
                    both of these flags are specified</strong> or
                    if the semaphore is read-only.
            </li>
        </ul>

        <p>When opening an existing semaphore, <span class="param">mode</span> is ignored.
        </p>
    </dd>

    <dt>acquire([timeout = None, [delta = 1]])</dt>
    <dd>Waits (conditionally) until the semaphore's value is &gt; 0 and then
        returns, decrementing the semaphore.

        <p>The <span class="param">timeout</span> (which can be a float) specifies how
            many seconds this call should wait, if at all.
        </p>
        <p>The semantics of the timeout <a href="#v0_3">changed a little in
            version 0.3</a>.
        </p>

        <ul>
            <li>A <span class="param">timeout</span> of None (the default)
                implies no time limit. The call will not return until its wait
                condition is satisfied.
            </li>

            <li>When <span class="param">timeout</span> is 0, the call
                raises a <tt>BusyError</tt> if it can't immediately
                acquire the semaphore. Since it will
                return immediately if <em>not</em> asked to wait, this can be
                thought of as "non-blocking" mode.
            </li>

            <li>When the <span class="param">timeout</span> is &gt; 0, the call
                will wait no longer than <span class="param">timeout</span>
                seconds before either returning (having acquired the semaphore)
                or raising a <tt>BusyError</tt>.
            </li>
        </ul>

        <p>When the call returns, the semaphore's value decreases by
            <span class="param">delta</span>
            (or more precisely, <tt>abs(<span class="param">delta</span>)</tt>)
            which defaults to 1.
        </p>

        <p>On platforms that don't support the <tt>semtimedop()</tt> API call,
            all timeouts (including zero) are treated as infinite. The call
            will not return until its wait condition is satisfied.
        </p>

        <p>Most platforms provide <tt>semtimedop()</tt>. OS X is a
            notable exception. The module's Boolean constant
            <tt>SEMAPHORE_TIMEOUT_SUPPORTED</tt>
            is True on platforms that support <tt>semtimedop()</tt>.
        </p>
    </dd>


    <dt>release([delta = 1])</dt>
    <dd>
        Releases (increments) the semaphore.

        <p>The semaphore's value increases by <span class="param">delta</span>
            (or more precisely, <tt>abs(<span class="param">delta</span>)</tt>)
            which defaults to 1.
        </p>
    </dd>

    <dt>P()</dt>
    <dd>A synonym for <tt>.acquire()</tt> that takes the same parameters.

        <p>"P" stands for
        <span lang="nl">prolaag</span> or <span lang="nl">probeer te verlagen</span>
        (try to decrease), the original name given by
        <a href="http://en.wikipedia.org/wiki/Semaphore_(programming)">Edsger Dijkstra</a>.
        </p>
    </dd>

    <dt>V()</dt>
    <dd>A synonym for <tt>.release()</tt> that takes the same parameters.

        <p>"V" stands for
        <span lang="nl">verhoog</span> (increase), the original name given by
        <a href="http://en.wikipedia.org/wiki/Semaphore_(programming)">Edsger Dijkstra</a>.
        </p>
    </dd>

    <dt>Z([timeout = None])</dt>
    <dd>Blocks until zee zemaphore is zero.

        <p><span class="param">Timeout</span> has
            the same meaning as described in <tt>.acquire()</tt>.
        </p>
    </dd>

    <dt>remove()</dt>
    <dd>
        Removes (deletes) the semaphore from the system.

        <p>As far as I can tell, the effect of deleting a semaphore that
            other processes are still using is OS-dependent. Check your system's
            man pages for <tt>semctl(IPC_RMID)</tt>.
        </p>
    </dd>
</dl>

<h4>Attributes</h4>

<dl>
    <dt>key (read-only)</dt>
    <dd>The key passed in the call to the constructor.</dd>

    <dt>id (read-only)</dt>
    <dd>The id assigned to this semaphore by the OS.</dd>

    <dt>value</dt>
    <dd>The integer value of the semaphore.</dd>

    <dt>undo</dt>
    <dd>Defaults to False.

        <p>When True, operations that change the
        semaphore's value will be undone (reversed) when
        the process exits. Note that when a process exits, an undo operation
        may imply that a semaphore's value should become negative or
        exceed its maximum.
        Behavior in this case is system-dependent, which means that
        <strong>using this flag can make your code non-portable</strong>.
        </p>
    </dd>

    <dt>block</dt>
    <dd>
        Defaults to True, which means that calls to <tt>acquire()</tt> and
        <tt>release()</tt> will not return
        until their wait conditions are satisfied.

        <p>When False, these calls
        will not block but will instead raise an error if they are unable
        to return immediately.
        </p>
    </dd>

    <dt>mode</dt>
    <dd>The semaphore's permission bits.

        <p>Tip: the following Python code will display
        the mode in octal:<br>
        <tt>print int(str(my_sem.mode), 8)</tt>
        </p>
    </dd>

    <dt>uid</dt>
    <dd>The semaphore's user id.</dd>

    <dt>gid</dt>
    <dd>The semaphore's group id.</dd>

    <dt>cuid (read-only)</dt>
    <dd>The semaphore creator's user id.</dd>

    <dt>cgid (read-only)</dt>
    <dd>The semaphore creator's group id.</dd>

    <dt>last_pid (read-only)</dt>
    <dd>The PID of the process that last called <tt>semop()</tt> (<tt>.P()</tt>,
        <tt>.V()</tt> or <tt>.Z()</tt>) on this semaphore.
    </dd>

    <dt>waiting_for_nonzero (read-only)</dt>
    <dd>The number of processes waiting for the value of the semaphore to become
        non-zero (i.e. the number waiting in a call to <tt>.P()</tt>).
    </dd>

    <dt>waiting_for_zero (read-only)</dt>
    <dd>The number of processes waiting for the value of the semaphore to become
        zero (i.e. the number waiting in a call to <tt>.Z()</tt>).
    </dd>

    <dt>o_time (read-only)</dt>
    <dd>The last time <tt>semop()</tt> (i.e. <tt>.P()</tt>, <tt>.V()</tt> or
        <tt>.Z()</tt>) was called on this semaphore.
    </dd>
</dl>

<h4>Context Manager Support</h4>

<p>These semaphores provide <tt>__enter__()</tt> and <tt>__exit__()</tt>
methods so they can be used in context managers. For instance --
</p>

<pre>
with sysv_ipc.Semaphore(name) as sem:
    # Do something...
</pre>

<p>Entering the context acquires the semaphore, exiting the context releases
	the semaphore. See <tt>demo4/child.py</tt> for a complete example.
</p>


<h3 id="shared_memory">The SharedMemory Class</h3>

<p>This is a handle to a shared memory segment.
</p>


<h4>Methods</h4>

<dl>
    <dt>SharedMemory(key, [flags = 0, [mode = 0600, [size = 0 or PAGE_SIZE, [init_character = ' ']]]])</dt>
    <dd>Creates a new shared memory segment or opens an existing one.
        The memory is automatically attached.

        <p><span class="param">key</span> must be <tt>None</tt>,
            <tt>IPC_PRIVATE</tt> or
        an integer &gt; <tt>0</tt> and &le; <tt>KEY_MAX</tt>. If the key
        is <tt>None</tt>, the module chooses a random unused key.
        </p>

        <p>The <span class="param">flags</span> specify whether you want to create a
            new shared memory segment or open an existing one.
        </p>

        <ul>
            <li>With <span class="param">flags</span> set to the
                <strong>default</strong> of <tt>0</tt>, the module attempts
                to <strong>open an existing</strong> shared memory segment identified by
                <span class="param">key</span> and raises
                a <tt>ExistentialError</tt> if it doesn't exist.
            </li>

            <li>With <span class="param">flags</span> set to <strong><tt>IPC_CREAT</tt></strong>, the module
                <strong>opens</strong> the shared memory segment identified
                by <span class="param">key</span> <strong>or
                creates</strong> a new one if no such segment exists.
                Using <tt>IPC_CREAT</tt> by itself
                is not recommended. (See <a href="#mem_init">Memory Initialization</a>.)
            </li>

            <li>With <span class="param">flags</span> set to
                <strong><tt>IPC_CREX</tt></strong> (<tt>IPC_CREAT | IPC_EXCL</tt>),
                the module
                <strong>creates</strong> a new shared memory segment identified by
                <span class="param">key</span>. If
                a segment with that key already exists, the call raises
                a <tt>ExistentialError</tt>.

                <p>When both <tt>IPC_CREX</tt> is specified
                    and the caller has write permission, each byte in the new memory segment will be
                    initialized to the value of <span class="param">init_character</span>.
                </p>
            </li>
        </ul>

        <p>The value of <span class="param">size</span> depends on whether
            one is opening an existing segment or creating a new one.
        </p>
        <ul>
            <li>When opening an existing segment, <span class="param">size</span>
                must be ≤ the existing segment's size. Zero is
                always valid.
            </li>

            <li>When creating an new segment,
                many (most? all?) operating systems insist on a <span class="param">size</span>
                &gt; <tt>0</tt>.
                In addition, some round the size
                up to the next multiple of PAGE_SIZE.
            </li>
        </ul>

        <p>This module supplies a default
            <span class="param">size</span> of <tt>PAGE_SIZE</tt> when
            <tt>IPC_CREX</tt> is specified and <tt>0</tt> otherwise.
        </p>
    </dd>

    <dt id="attach">attach([address = None, [flags = 0]])</dt>
    <dd>
        Attaches this process to the shared memory. The memory must be attached
        before calling <tt>.read()</tt> or <tt>.write()</tt>. Note that the
        constructor automatically attaches the memory
        so you won't need to call this method unless you explicitly detach it
        and then want to use it again.

        <p>The address parameter allows one to specify (as a Python long) a memory
            address at which to attach the segment. Passing None (the default)
            is equivalent to passing NULL to <tt>shmat()</tt>. See that
            function's man page for details.
        </p>

        <p>The flags are mostly only relevant if one specifies a specific address.
            One exception is the flag <tt>SHM_RDONLY</tt> which, surprisingly,
            attaches the segment read-only.
        </p>

        <p>Note that on some (and perhaps all) platforms, each call to <tt>.attach()</tt>
            increments the system's "attached" count. Thus, if each call to
            <tt>.attach()</tt> isn't paired with a call to <tt>.detach()</tt>,
            the system's "attached" count for the shared memory segment will not
            go to zero when the process exits. As a result, the shared memory
            segment may not disappear even when its creator calls <tt>.remove()</tt>
            and exits.
        </p>
    </dd>

    <dt>detach()</dt>
    <dd>Detaches this process from the shared memory.</dd>

    <dt>read([byte_count = 0, [offset = 0]])</dt>
    <dd>Reads up to <span class="param">byte_count</span> bytes from the
        shared memory segment starting at <span class="param">offset</span>
        and returns them as a string under Python 2 or as a bytes object
        under Python 3.

        <p>If <span class="param">byte_count</span> is zero (the default) the
            entire buffer is returned.
        </p>

        <p>This method will never attempt to read past the end of the shared
            memory segment, even when
            <span class="param">offset</span> + <span class="param">byte_count</span>
            exceeds the memory segment's size. In that case, the bytes
            from <span class="param">offset</span> to the end of the segment are returned.
        </p>
    </dd>

    <dt>write(s, [offset = 0])</dt>
    <dd>Writes the string <span class="param">s</span> to the shared memory,
        starting at <span class="param">offset</span>.

        <p>At most <tt><i>n</i></tt> bytes will be written, where
            <tt><i>n</i></tt> = the segment's size minus <span class="param">offset</span>.
        </p>

        <p>The string may contain embedded NULL bytes ('\0').
    </dd>

    <dt>remove()</dt>
    <dd>Removes (destroys) the shared memory. Note that actual destruction of the
        segment only occurs when all processes have detached.
    </dd>

</dl>

<h4>Attributes</h4>

<dl>
    <dt>key (read-only)</dt>
    <dd>The key provided in the constructor.</dd>

    <dt>id (read-only)</dt>
    <dd>The id assigned to this semaphore by the OS.</dd>

    <dt>size (read-only)</dt>
    <dd>The size of the segment in bytes.</dd>

    <dt>address (read-only)</dt>
    <dd>The address of the segment as Python long.</dd>

    <dt>attached (read-only)</dt>
    <dd>If True, this segment is currently attached.</dd>

    <dt>last_attach_time (read-only)</dt>
    <dd>The last time a process attached this segment.</dd>

    <dt>last_detach_time (read-only)</dt>
    <dd>The last time a process detached this segment.</dd>

    <dt>last_change_time (read-only)</dt>
    <dd>The last time a process changed the uid, gid or mode on this segment.</dd>

    <dt>creator_pid (read-only)</dt>
    <dd>The PID of the process that created this segment.</dd>

    <dt>last_pid (read-only)</dt>
    <dd>The PID of the most last process to attach or detach this segment.</dd>

    <dt>number_attached (read-only)</dt>
    <dd>The number of processes attached to this segment.</dd>

    <dt>uid</dt>
    <dd>The segment's user id.</dd>

    <dt>gid</dt>
    <dd>The segment's group id.</dd>

    <dt>mode</dt>
    <dd>The shared memory's permission bits.

        <p>Tip: the following Python code will display
        the mode in octal:<br>
        <tt>print int(str(my_mem.mode), 8)</tt>
        </p>
    </dd>

    <dt>cuid (read-only)</dt>
    <dd>The segment creator's user id.</dd>

    <dt>cgid (read-only)</dt>
    <dd>The segment creator's group id.</dd>
</dl>


<h3 id="message_queue">The MessageQueue Class</h3>

<p>This is a handle to a message queue.</p>

<h4>Methods</h4>

<dl>
    <dt>MessageQueue(key, [flags = 0, [mode = 0600, [max_message_size = 2048]]])</dt>
    <dd>Creates a new message queue or opens an existing one.

        <p><span class="param">key</span> must be <tt>None</tt>,
            <tt>IPC_PRIVATE</tt> or
        an integer &gt; <tt>0</tt> and &le; <tt>KEY_MAX</tt>. If the key
        is <tt>None</tt>, the module chooses a random unused key.
        </p>

        <p>The <span class="param">flags</span> specify whether you want to create a
            new queue or open an existing one.
        </p>

        <ul>
            <li>With <span class="param">flags</span> set to the
                <strong>default</strong> of <tt>0</tt>, the module attempts
                to <strong>open an existing</strong> message queue identified by
                <span class="param">key</span> and raises
                a <tt>ExistentialError</tt> if it doesn't exist.
            </li>

            <li>With <span class="param">flags</span> set to <strong><tt>IPC_CREAT</tt></strong>, the module
                <strong>opens</strong> the message queue identified
                by <span class="param">key</span> <strong>or
                creates</strong> a new one if no such queue exists.
            </li>

            <li>With <span class="param">flags</span> set to
                <strong><tt>IPC_CREX</tt></strong> (<tt>IPC_CREAT | IPC_EXCL</tt>),
                the module
                <strong>creates</strong> a new message queue identified by
                <span class="param">key</span>. If
                a queue with that key already exists, the call raises
                a <tt>ExistentialError</tt>.
            </li>
        </ul>

        <p>The <span class="param">max_message_size</span> can be increased
            from the default, but be aware of the issues discussed in
            <a href="#message_queue_limits">Message Queue Limits</a>.
        </p>
    </dd>

    <dt>send(message, [block = True, [type = 1]])</dt>
    <dd>Puts a message on the queue.

        <p>The <span class="param">message</span> string can contain embedded
            NULLs (ASCII <tt>0x00</tt>).
        </p>

        <p>The <span class="param">block</span> flag specifies whether or
            not the call should wait if the message can't be sent (if, for
            example, the queue is full). When <span class="param">block</span>
            is <tt>False</tt>, the call will raise a <tt>BusyError</tt> if
            the message can't be sent immediately.
        </p>

        <p>The <span class="param">type</span> is
            associated with the message and is relevant when calling
            <tt>receive()</tt>. It must be &gt; 0.
        </p>
    </dd>

    <dt>receive([block = True, [type = 0]])</dt>
    <dd>
        Receives a message from the queue, returning a tuple of
        <tt>(message, type)</tt>. Under Python 3, the message is a
        bytes object.

        <p>The <span class="param">block</span> flag specifies whether or
            not the call should wait if there's no messages of the
            specified type to retrieve. When <span class="param">block</span>
            is <tt>False</tt>, the call will raise a <tt>BusyError</tt> if
            a message can't be received immediately.
        </p>

        <p>The <span class="param">type</span> permits some control over
            which messages are retrieved.
        </p>

        <ul>
            <li>When <span class="param">type</span> <tt>== 0</tt>, the call
                returns the first message on the queue regardless of its
                type.
            </li>
            <li>When <span class="param">type</span> <tt>&gt; 0</tt>, the call
                returns the first message of that type.
            </li>
            <li>When <span class="param">type</span> <tt>&lt; 0</tt>, the call
                returns the first message of the lowest type that is ≤ the
                absolute value of <span class="param">type</span>.
            </li>
        </ul>
    </dd>

    <dt>remove()</dt>
    <dd>Removes (deletes) the message queue.</dd>
</dl>

<h4>Attributes</h4>

<dl>
    <dt>key (read-only)</dt>
    <dd>The key provided in the constructor.</dd>

    <dt>id (read-only)</dt>
    <dd>The id assigned to this queue by the OS.</dd>

    <dt id="queue_max_size">max_size</dt>
    <dd>The maximum size of the queue in bytes. Only a process with
        "appropriate privileges" can increase this value, and on some
        systems even that won't work. See
        <a href="#message_queue_limits">Message Queue Limits</a> for details.
    </dd>

    <dt>last_send_time (read-only)</dt>
    <dd>The last time a message was placed on the queue.</dd>

    <dt>last_receive_time (read-only)</dt>
    <dd>The last time a message was received from the queue.</dd>

    <dt>last_change_time (read-only)</dt>
    <dd>The last time a process changed the queue's attributes.</dd>

    <dt>last_send_pid (read-only)</dt>
    <dd>The id of the most recent process to send a message.</dd>

    <dt>last_receive_pid (read-only)</dt>
    <dd>The id of the most recent process to receive a message.</dd>

    <dt>current_messages (read-only)</dt>
    <dd>The number of messages currently in the queue.</dd>

    <dt>uid</dt>
    <dd>The queue's user id.</dd>

    <dt>gid</dt>
    <dd>The queue's group id.</dd>

    <dt>mode</dt>
    <dd>The queue's permission bits.

        <p>Tip: the following Python code will display
        the mode in octal:<br>
        <tt>print int(str(my_mem.mode), 8)</tt>
        </p>
    </dd>

    <dt>cuid (read-only)</dt>
    <dd>The queue creator's user id.</dd>

    <dt>cgid (read-only)</dt>
    <dd>The queue creator's group id.</dd>
</dl>



<h3>Supported Features and Differences from SHM</h3>

<p>This module is almost, but not quite, a superset of
<a href="http://nikitathespider.com/python/shm/"><tt>shm</tt></a>.
Some of the additional features are the ability to override the <tt>block</tt>
flag on a per-call basis, the ability to change the semaphore's value
in increments &gt; 1 when calling <tt>.P()</tt> and <tt>.V()</tt>
and exposure of <tt>sem_otime</tt>.
</p>

<p>Differences that might trip you up are listed below.</p>

<ul>
    <li><tt>Shm</tt> compiles under Python 2.3 and older; this module has
        not been tested with Python older than 2.4
    </li>
    <li>Attribute names and method signatures are different.</li>
    <li>This module offers neither the functions <tt>semaphore_haskey()</tt>
        nor <tt>memory_haskey()</tt>.
    </li>
    <li>This module's default permission on objects is <tt>0600</tt> as opposed
        to <tt>shm</tt>'s <tt>0666</tt>.
    </li>
    <li><tt>Shm</tt> maintained an internal dictionary of semaphores and shared memory
        segments. The object keys served as the dictionary keys.
        If you asked for the same object multiple times, <tt>shm</tt> would
        return the same Python object. I'm not convinced this was safe,
        particularly in the case where an object may have been destroyed
        and another with the same key created in its place.
    </li>
</ul>

<h3>Usage Tips</h3>

<h4>Sample Code</h4>

<p>This module comes with two demonstration apps. The first (in the
directory <tt>demo</tt>) shows how to use shared memory and semaphores.
The second (in the directory <tt>demo2</tt>) shows how to use
message queues.


<h4 id="ftok_weakness">The Weakness of <tt>ftok()</tt></h4>

<p>
Most System V IPC sample code recommends <tt>ftok()</tt> for generating an
integer key that's more-or-less random.
It does not, however, guarantee that the key it generates is unused. If
<tt>ftok()</tt> gives your application a key that some other application is
already using,
your app is in trouble unless it has a reliable second mechanism for generating
a key. And if that's the case, why not just abandon <tt>ftok()</tt> and use the
second mechanism exclusively?
</p>

<p>This is the weakness of <tt>ftok()</tt> -- it isn't guaranteed to give you
what you want. The <a href="http://www.unix.com/man-page/FreeBSD/3/ftok/">BSD
man page for <tt>ftok</tt></a> says it is "quite possible for the routine to
return duplicate keys". The term "quite possible" isn't quantified, but suppose
it means one-tenth of one percent. Who wants to have 1-in-1000 odds of a
catastrophic failure in their program, or even 1-in-10000?
</p>

<p>This module obviates the need for <tt>ftok()</tt> by generating random
keys for you. If your application can't use <tt>sysv_ipc</tt>'s automatically
generated keys because it needs to know the key in advance, hardcoding a
random number like 123456 in your app might be no worse than using
<tt>ftok()</tt> and has the advantage of not hiding its limitations.
</p>

<p>This module provides <tt>ftok()</tt> in case you want to experiment with it.
However, to emphasize its weakness, this version of <tt>ftok()</tt> raises a
warning with every call unless you explicitly pass a flag to silence it.
</p>

<p>This package also provides <tt>ftok_experiment.py</tt> so that you can observe
how often <tt>ftok()</tt> generates duplicate keys on your system.
</p>


<h4 id="sem_init">Semaphore Initialization</h4>

<p>When a System V sempahore is created at the C API level, the OS is not required
to initialize the semaphore's value. (This per
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/semget.html">the
SUSv3 standard for <tt>semget()</tt></a>.)
Some (most? all?) operating systems initialize it to zero, but this behavior
is non-standard and therefore can't be relied upon.
</p>

<p>If sempahore creation happens in an predictable, orderly fashion, this isn't a
problem. But a
race condition arises when multiple processes vie to create/open the same semaphore. The
problem lies in the fact that when an application calls <tt>semget()</tt> with only
the <tt>IPC_CREAT</tt> flag, the caller can't tell whether or not he has
created a new semaphore or opened an existing one.
<strong>This makes it
difficult to create reliable code without using <tt>IPC_EXCL</tt>.</strong>
W. Richard Stevens' <span class='book_title'>Unix Network Programming Volume 2</span>
calls this "a fatal flaw in the design of System V semaphores" (p 284).
</p>

<p>
For instance, imagine processes P1 and P2. They're executing the same code,
and that code intends to share a binary semaphore.
Consider the following sequence of events at the startup of P1 and P2 &ndash;
</p>

<ol>
    <li>P1 calls <tt>semget(IPC_CREAT)</tt> to create the semaphore S.</li>
    <li>P2 calls <tt>semget(IPC_CREAT)</tt> to open S.</li>
    <li>P1 initializes the semaphore's value to 1.</li>
    <li>P1 calls <tt>acquire()</tt>, decrementing the value to 0.</li>
    <li>P2, assuming S is a newly-created semaphore that needs to be initialized,
        incorrectly sets the semaphore's value to 1.</li>
    <li>P2 calls <tt>acquire()</tt>, decrementing the value to 0. Both processes
        now think they own the lock.</li>
</ol>

<p>W. Richard Stevens' solution for this race condition is to check the value of
<tt>sem_otime</tt> (an element in the <tt>semid_ds</tt> struct that's
populated on the call to <tt>semctl(IPC_STAT)</tt> and which is exposed to
Python by this module) which
is initialized to zero when the semaphore is created and otherwise holds
the time of the last
call to <tt>semop()</tt> (which is called by <tt>P()</tt>/<tt>acquire()</tt>,
<tt>V()</tt>/<tt>release()</tt>, and <tt>Z()</tt>).
</p>

<p>In Python, each process would run something like this:
<pre>
try:
    sem = sysv_ipc.Semaphore(42, sysv_ipc.IPC_CREX)
except sysv_ipc.ExistentialError:
    # One of my peers created the semaphore already
    sem = sysv_ipc.Semaphore(42)
    # Waiting for that peer to do the first acquire or release
    while not sem.o_time:
        time.sleep(.1)
else:
    # Initializing sem.o_time to nonzero value
    sem.release()
# Now the semaphore is safe to use.
</pre>


<h4 id="mem_init">Shared Memory Initialization</h4>

<p>With shared memory,
using the <tt>IPC_CREAT</tt> flag without <tt>IPC_EXCL</tt>
is problematic <em>unless you know the size of the segment
you're potentially opening</em>.
</p>

<p>Why? Because when creating a new segment,
many (most? all?) operating systems demand a non-zero size. However,
when opening an existing segment, zero is the only guaranteed safe value
(again, assuming one doesn't know the size of the segment in advance).
Since <tt>IPC_CREAT</tt>
can open or create a segment, there's no safe value for the size under
this circumstance.
</p>

<p>As a (sort of) side note, the
<a href="http://www.opengroup.org/onlinepubs/009695399/functions/shmget.html">SUSv3
specification for <tt>shmget()</tt></a> says only that the size of a new
segment must not be less than "the system-imposed minimum". I
gather that at one time, some systems set the minimum at zero despite the
fact that it doesn't make much sense to create a zero-length shared memory
segment. I think most modern systems do the sensible thing and insist on
a minimum length of 1.
</p>


<h4 id="message_queue_limits">Message Queue Limits</h4>

<p>Python programmers can usually remain blissfully ignorant of memory
allocation issues. Unfortunately, a combination of factors makes them
relevant when dealing with System V message queues.
</p>

<p><strong>Some implementations impose extremely stingy limits.</strong>
For instance, many BSDish systems (OS X, FreeBSD,
<a href="http://fxr.watson.org/fxr/source/sys/msg.h?v=NETBSD">NetBSD</a>, and
<a href="http://fxr.watson.org/fxr/source/sys/msg.h?v=OPENBSD">OpenBSD</a>)
limit queues to 2048 bytes. Note that that's the <em>total
queue size</em>, not the message size. Two 1k messages would fill the queue.
</p>

<p><strong>Those limits can be very difficult to change.</strong> At best,
only privileged processes can increase the limit. At worst, the limit
is a kernel parameter and requires a kernel change via a tunable or
a recompile.
</p>

<p><strong>This module can't figure out what the limits are</strong>, so
it can't cushion them or even report them to you.
On some systems the limits are expressed in header files, on others
they're available through kernel interfaces (like FreeBSD's <tt>sysctl</tt>).
Under OS X and to some extent OpenSolaris I can't figure out where they're
defined and what I report here is the result of experimentation and educated
guesses formed by Googling.
</p>

<p>The good news is that this module will still behave as advertised no
matter what these limits are. Nevertheless you might be surprised when a
call to <tt>.send()</tt> get stuck because a queue is full even though you've
only put 2048 bytes of messages in it.
</p>

<p>Here are the limits I've been able to find under my test operating
systems, ordered from best (most generous) to worst (most stingy).
<strong>This information was current as of 2009</strong> when I wrote the
message queue code. It's getting pretty stale now. I hope the situation has
improved over the 2009 numbers I describe below.
</p>

<p>Under <strong>OpenSolaris 2008.05</strong> each queue's maximum size defaults
to 64k. A privileged process (e.g. root) can change this through the
<tt>max_size</tt> attribute of a <tt>sysv_ipc.MessageQueue</tt> object.
I was able to increase it to 16M and successfully sent sixteen 1M messages to
the queue.
</p>

<p>Under <strong>Ubuntu 8.04</strong> (and perhaps other Linuxes) each
queue's maximum size defaults to 16k. As with OpenSolaris, I was able to
increase this to 16M, but only for a privileged process.
</p>

<p>Under <strong>FreeBSD 7</strong> and I think NetBSD and OpenBSD, each
queue's maximum size defaults to 2048 bytes. Furthermore, one can (as root)
set <tt>max_size</tt> to something larger and FreeBSD doesn't complain, but
it also ignores the change.
</p>

<p><strong>OS X</strong> is the worst of the lot. Each queue is limited
to 2048 bytes and OS X silently ignores attempts to increase this (just like
FreeBSD). To add insult to injury, there appears to be no way to increase
this limit short of recompiling the kernel.
I'm guessing at this based on the
<a href="http://www.google.com/search?q=site%3Aopensource.apple.com+%22msg.h%22">Darwin
message queue limits</a>.
</p>

<p>If you want
to search for these limits on your operating system, the key constants are
<tt>MSGSEG</tt>, <tt>MSGSSZ</tt>, <tt>MSGTQL</tt>, <tt>MSGMNB</tt>,
<tt>MSGMNI</tt> and <tt>MSGMAX</tt>. Under BSD, <tt>sysctl kern.ipc</tt>
should tell you what you need to know and may allow you to change these
parameters.
</p>

<h4>Nobody Likes a Mr. Messy</h4>

<p>Semaphores and especially shared memory are a little different from most Python objects
and therefore require a little more care on the part of the programmer. When a
program creates a semaphore or shared memory object, it creates something that
resides <em>outside of its own process</em>, just like a file on a hard drive. It
won't go away when your process ends unless you explicitly remove it.
</p>

<p>In short, remember to clean up after yourself.</p>

<h4>Consult Your Local <tt>man</tt> Pages</h4>

<p>The sysv_ipc module is just a wrapper around your system's API. If your
system's implementation has quirks, the <tt>man</tt> pages for <tt>semget, semctl, semop
shmget, shmat, shmdt</tt> and <tt>shmctl</tt> will probably cover them.
</p>

<h4>Interesting Tools</h4>

<p>Many systems (although not some older versions of OS X) come
with <tt>ipcs</tt> and <tt>ipcrm</tt>.
The former shows existing shared memory, semaphores and message queues on your system and
the latter allows you to remove them.
</p>


<h4>Last But Not Least</h4>

<p>For Pythonistas &ndash;</p>
<ul>
    <li><a href="https://www.youtube.com/watch?v=Xe1a1wHxTyo">A meditation on the inaccuracy
        of shared memories</a>
    </li>
</ul>

<h3 id="bugs">Known Bugs</h3>

<p>Bugs? My code never has bugs! There are, however, some suboptimal anomalies...</p>

<ul>
    <li>Under OS X, <tt>sys/ipc.h</tt> defines two versions of the
        <tt>ipc_perm</tt> struct. This module picks up the old, deprecated
        one which stores uid and gid values in 16 bit types. It's definitions
        in <tt>Python.h</tt> that cause this, though, so there's not much
        I can do to change it.
    </li>
    <li>This module can't report the exact min and max values for a key.
        It turns out
        that <a href="http://groups.google.com/group/comp.lang.c/browse_thread/thread/14a1cdbfb111f4eb">it's
        really difficult to determine the maximum value that a
        typedef-ed variable can hold</a>.
    </li>
</ul>

<h3>Version History</h3>

<ul id="history">
    <li id="v0_6_8"><strong><span id="current">Current</span> &ndash; 0.6.8 (12 Sept 2014) &ndash;</strong>
        <ul>
            <li>Fixed a bug in <tt>prober.py</tt> where prober would fail
            	on systems where Python's include file was not named
            	<tt>pyconfig.h</tt>. (RHEL 6 is one such system.) Thanks to
            	Joshua Harlow for the bug report and patch.
            </li>

    		<li><i>Spasibo</i> again to Yuriy Taraday for pointing out that
    			the semaphore initialization example I changed in the previous
    			version was still not
    			quite correct, and for suggesting something better.
    		</li>
        </ul>
    </li>

    <li id="v0_6_7">0.6.7 (1 August 2014) &ndash;
    	<p><i>Spasibo</i> to Yuriy Taraday for reporting some doc errors
    		corrected in this version.
    	</p>

        <ul>
            <li>Added KEY_MIN as a module-level constant. The documentation
            	has claimed that it was available for a long time so now the
            	code finally matches the documentation.
            </li>

            <li>Changed randomly generated keys to never use a value of 0.</li>

            <li>Fixed two documenation errors in the special section on
            	semaphore initialization and gave long overdue credit to
            	W. Richard Stevens' book for the code idea. (Any code mistakes
            	are mine, not his.)
            </li>

            <li>This is the first version downloadable from PyPI.</li>
        </ul>
    </li>

    <li id="v0_6_6">0.6.6 (15 October 2013) &ndash;
        <p>Added the ability to use Semaphores in context managers.
        	Thanks to Matt Ruffalo for the suggestion and patch.
        </p>
    </li>

    <li id="v0_6_5">0.6.5 (31 March 2013) &ndash;
		<p>Fixed a bug where SharedMemory.write() claimed to accept
            	keyword arguments but didn't actually do so. Thanks to
            	Matt Ruffalo for the bug report and patch.
        </p>
    </li>

    <li id="v0_6_4">0.6.4 (19 Dec 2012) &ndash;
        <ul>
            <li>Added a module-level <tt>attach()</tt> method based on a
            	suggestion by Vladimír Včelák.
            </li>
            <li>Added the <tt>ftok()</tt> method along with dire warnings about
            	its use.
            </li>
        </ul>
    </li>

    <li id="v0_6_3">0.6.3 (3 Oct 2010) &ndash;
        <ul>
            <li>Fixed a segfault in <tt>write()</tt> that occurred any time
                an offset was passed. This was introduced in v0.6.0.
                <i>Tack</i> to Johan Bernhardtson for the bug report.
            </li>
        </ul>
    </li>

    <li id="v0_6_2">0.6.2 (6 July 2010) &ndash;
        <ul>
            <li>Updated setup.py metadata to reflect Python 3 compatibility.
                No functional change.
            </li>
        </ul>
    </li>

    <li id="v0_6_1">0.6.1 (26 June 2010) &ndash;
        <ul>
            <li>Fixed a typo introduced in the previous version that caused
                unpredictable behavior (usually a segfault) if a block flag
                was passed to <tt>MessageQueue.send()</tt>. <i>Obrigado</i>
                to Álvaro Justen and Ronald Kaiser for the bug report and
                patch.
            </li>
        </ul>
    </li>

    <li id="v0_6_0">0.6.0 (20 May 2010) &ndash;
        <ul>
            <li>Added Python 3 support.</li>
            <li>Renamed a constant that caused a problem under AIX.
                Thanks to Loic Nageleisen for the bug report.
            </li>
            <li>Updated this documentation a little.</li>
        </ul>
    </li>

    <li id="v0_5_2">0.5.2 (17 Jan 2010)</strong>
        <ul>
            <li>Fixed a bug that insisted on keys &gt; 0. Thanks to 原志
                (Daniel) for the bug report and patch.
            </li>
            <li>Fixed a bug where the module could have generated invalid
                keys on systems that typedef <tt>key_t</tt> as a
                <tt>short</tt>. I don't think such a system exists, though.
            </li>
            <li>Fixed a LICENSE file typo.</li>
            <li>Added an RSS feed to this page.</li>
        </ul>
    </li>

    <li id="v0_5_1">0.5.1 (1 Dec 2009) &ndash;
        <p>No code changes in this version.</p>
        <ul>
            <li>Fixed the comment in <tt>sysv_ipc_module.c</tt> that
                still referred to the GPL license.
            </li>
            <li>Added the attributes <tt>__version</tt>, <tt>__author__</tt>,
                <tt>__license__</tt> and <tt>__copyright__</tt>.
            </li>
            <li>Removed <tt>file()</tt> from <tt>setup.py</tt> in favor
                of <tt>open()</tt>.
            </li>
        </ul>
    </li>

    <li id="v0_5">0.5 (6 Oct 2009) &ndash;
        <p>No code changes in this version.</p>
        <ul>
            <li>Changed the license from GPL to BSD.</li>
        </ul>
    </li>

    <li id="v0_4_2">0.4.2 (22 Mar 2009) &ndash;
        <p>No code changes in this version.</p>
        <ul>
            <li>Fixed broken documentation links to youtube.</li>
            <li>Fixed the project name in the LICENSE file.</li>
        </ul>
    </li>

    <li id="v0_4_1"> 0.4.1 (12 Feb 2009) &ndash;
        <ul>
            <li>Changed status to beta.</li>
            <li>Added automatic generation of keys.</li>
            <li>Added a message queue demo.</li>
            <li>Added <tt>str()</tt> and <tt>repr()</tt> support to all
                objects.</li>
            <li>Fixed a bug in <tt>SharedMemory.write()</tt> that could cause
                a spurious error of "Attempt to write past end of memory
                segment". This bug only occurred on platforms using
                different sizes for <tt>long</tt> and <tt>int</tt>, or
                <tt>long</tt> and <tt>py_size_t</tt>
                (depending on Python version). <em>Tack</em> to Jesper
                for debug help.
            </li>
            <li>Plugged a memory leak in <tt>MessageQueue.receive()</tt>.</li>
            <li>Added a VERSION attribute to the module.</li>
        </ul>
    </li>

    <li id="v0_4">0.4 (28 Jan 2009) &ndash;
        <ul>
            <li>Added message queues.</li>
            <li>Fixed a bug where the <tt>key</tt> attribute of SharedMemory objects
                returned garbage.
            </li>
            <li>Fixed a bug where keys &gt; INT_MAX would get truncated on
                platforms where longs are bigger than ints.
            </li>
            <li>Provided decent inline documentation for object attributes
                (available via the <tt>help()</tt> command).
            </li>
            <li>Rearranged the code which was suffering growing pains.</li>
        </ul>
    </li>

    <li id="v0_3">0.3 (16 Jan 2009) &ndash;
        <p>This version features a rename of classes and errors
            (sorry about breaking the names), some modifications to
            semaphore timeouts, and many small fixes.
        </p>

        <p>A semaphore's <tt>.block</tt> flag now consistently trumps the
            timeout. When <tt>False</tt>, the timeout is irrelevant -- calls
            will never block. In prior versions, the flag was ignored
            when the timeout was non-zero.
        </p>

        <p>Also, on platforms (such as OS X) where <tt>semtimedop()</tt> is
            not supported, all timeouts are now treated as <tt>None</tt>.
            In other words, when <tt>.block</tt> is True, all calls
            wait as long as necessary.
        </p>

        <p>Other fixes &ndash;</p>

        <ul>
            <li>Fixed the poor choices I'd made for class and
                error names by removing the leading "SysV" and "SysVIpc".
            </li>
            <li>Removed dependencies on Python 2.5. The module now works
                with Python 2.4.4 and perhaps earlier versions.
            </li>
            <li>Fixed a bug where I was not following SysV semaphore semantics
                for interaction between timeouts and the block flag.
            </li>
            <li>Fixed compile problems on OpenSolaris 2008.05.</li>
            <li>Got rid of OS X compile warnings.</li>
            <li>Fixed many instances where I was making potentially lossy
                conversions between Python values and Unix-specific
                types like <tt>key_t</tt>, <tt>pid_t</tt>, etc.
            </li>
            <li>Fixed a bug in the SharedMemory <tt>attach()</tt> function
                 that would set an error string but not return an error
                 value if the passed address was not <tt>None</tt> or a long.
            </li>
            <li>Simplified the code a little.</li>
            <li>Restricted the semaphore <tt>acquire()</tt> and
                <tt>release()</tt> delta to be between SHORT_MIN and
                SHORT_MAX since
                <a href="http://opengroup.org/onlinepubs/007908775/xsh/semop.html">it
                    is a short in the SUSv2 spec</a>.
            </li>
            <li>Fixed a bug where calling <tt>acquire()</tt> or
                <tt>release()</tt> with a delta of <tt>0</tt> would call
                <tt>.Z()</tt> instead.
            </li>
            <li>Disallowed byte counts ≤ <tt>0</tt> in
                <tt>SharedMemory.read()</tt>
            </li>
            <li>Fixed a bug in the <tt>SharedMemory</tt> init code that
                could, under vanishingly rare circumstances, return failure
                without setting the error code.
            </li>
            <li>Removed some dead code relating to the <tt>.seq</tt> member
                of the <tt>sem_perm</tt> and <tt>shm_perm</tt> structs.
            </li>
            <li>Stopped accessing the non-standard <tt>key</tt>
                (a.k.a. <tt>_key</tt> and <tt>__key</tt>) element of the
                <tt>ipc_perm</tt> struct.
            </li>
            <li>Added code to ensure the module doesn't try to create
                a string that's larger than Python permits when reading
                from shared memory.
            </li>
        </ul>
    </li>

    <li>0.2.1 (3 Jan 2009) &ndash;
        <ul>
            <li>Fixed a bug that prevented the module-specific
                errors (<tt>ExistentialError</tt>, etc.) from
                being visible in the module.
            </li>
            <li>Fixed a bug that re-initialized shared memory with
                the init character when only <tt>IPC_CREAT</tt> was specified
                and an existing segment was opened.
            </li>
            <li>Fixed a bug that always defaulted the size of a shared
                memory segment to <tt>PAGE_SIZE</tt>. Updated code and
                documentation to use intelligent defaults. <em>Tack</em> to
                Jesper for the bug report.
            </li>
            <li>Several cosmetic changes. (Added more metadata to setup.py,
                added a newline to the end of probe_results.h to avoid
                compiler complaints, etc.)
            </li>
        </ul>
    </li>

    <li>0.2 (16 Dec 2008) &ndash;
        Lots of small fixes.

        <ul>
            <li>Fixed a bug where calling <tt>shm.remove()</tt> on shared
               memory that was already removed would cause a SystemError.
               (I wasn't setting the Python error before returning.)
            </li>

            <li>Fixed a couple of bugs that would cause the creation
                of a new, read-only shared memory segment to fail.
            </li>

            <li>Fixed a bug that would cause the creation
                of a new, read-only semaphore to fail.
            </li>

            <li>Added the constant <tt>IPC_CREX</tt>.</li>

            <li>Renamed (sorry) <tt>MAX_KEY</tt> to <tt>KEY_MAX</tt> and
                <tt>MAX_SEMAPHORE_VALUE</tt> to <tt>SEMAPHORE_VALUE_MAX</tt>
                to be consistent with the C naming convention in limits.h.
            </li>

            <li>Hardcoded <tt>SEMAPHORE_VALUE_MAX</tt> to 32767 until I can
                find a reliable way to determine it at install time.
            </li>

            <li>Changed prober.py to write out a C header file with
                platform-specific definitions in it.
            </li>

            <li>Replaced OSError in shared memory functions with custom
                errors from this module.
            </li>

            <li>Added code to raise a ValueError when an attempt is made
                to assign an out-of-range value to a semaphore.
            </li>

            <li>Added code to raise a ValueError when an out-of-range key
                is passed to a constructor.
            </li>

            <li>Fixed a bug in the demo program conclusion.c that caused
                some informational messages to be printed twice.
            </li>

            <li>Fixed some documentation bugs.</li>
        </ul>
    </li>
    <li>0.1 (4 Dec 2008) &ndash; Original (alpha) version.</li>
</ul>


<h3>Future Features/Changes</h3>

<p>These are features that may or may not be added depending on technical
difficulty, user interest and so forth.
</p>

<ul>
    <li>Update this documentation with a list of platforms that support semtimedop().</li>

    <li>Find a way to make <tt>SEMAPHORE_VALUE_MAX</tt> more accurate.</li>
</ul>

<p>I don't plan on adding support for semaphore sets.</p>


</body>
</html>