Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tools/regression/sockets/unix_gc/unix_gc.c
48254 views
1
/*-
2
* Copyright (c) 2007 Robert N. M. Watson
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
/*
28
* A few regression tests for UNIX domain sockets. Run from single-user mode
29
* as it checks the openfiles sysctl to look for leaks, and we don't want that
30
* changing due to other processes doing stuff.
31
*/
32
33
#include <sys/types.h>
34
#include <sys/signal.h>
35
#include <sys/socket.h>
36
#include <sys/sysctl.h>
37
#include <sys/un.h>
38
#include <sys/wait.h>
39
40
#include <netinet/in.h>
41
42
#include <err.h>
43
#include <errno.h>
44
#include <fcntl.h>
45
#include <limits.h>
46
#include <stdio.h>
47
#include <stdlib.h>
48
#include <string.h>
49
#include <unistd.h>
50
51
static int forcegc = 1;
52
static char dpath[PATH_MAX];
53
static const char *test;
54
55
static int
56
getsysctl(const char *name)
57
{
58
size_t len;
59
int i;
60
61
len = sizeof(i);
62
if (sysctlbyname(name, &i, &len, NULL, 0) < 0)
63
err(-1, "%s", name);
64
return (i);
65
}
66
67
static int
68
getopenfiles(void)
69
{
70
71
return (getsysctl("kern.openfiles"));
72
}
73
74
static int
75
getinflight(void)
76
{
77
78
return (getsysctl("net.local.inflight"));
79
}
80
81
static int
82
getdeferred(void)
83
{
84
85
return (getsysctl("net.local.deferred"));
86
}
87
88
static void
89
sendfd(int fd, int fdtosend)
90
{
91
struct msghdr mh;
92
struct message { struct cmsghdr msg_hdr; int fd; } m;
93
ssize_t len;
94
int after_inflight, before_inflight;
95
96
before_inflight = getinflight();
97
98
bzero(&mh, sizeof(mh));
99
bzero(&m, sizeof(m));
100
mh.msg_control = &m;
101
mh.msg_controllen = sizeof(m);
102
m.msg_hdr.cmsg_len = sizeof(m);
103
m.msg_hdr.cmsg_level = SOL_SOCKET;
104
m.msg_hdr.cmsg_type = SCM_RIGHTS;
105
m.fd = fdtosend;
106
len = sendmsg(fd, &mh, 0);
107
if (len < 0)
108
err(-1, "%s: sendmsg", test);
109
after_inflight = getinflight();
110
if (after_inflight != before_inflight + 1)
111
errx(-1, "%s: sendfd: before %d after %d\n", test,
112
before_inflight, after_inflight);
113
}
114
115
static void
116
close2(int fd1, int fd2)
117
{
118
119
close(fd1);
120
close(fd2);
121
}
122
123
static void
124
close3(int fd1, int fd2, int fd3)
125
{
126
127
close2(fd1, fd2);
128
close(fd3);
129
}
130
131
static void
132
close4(int fd1, int fd2, int fd3, int fd4)
133
{
134
135
close2(fd1, fd2);
136
close2(fd3, fd4);
137
}
138
139
static void
140
close5(int fd1, int fd2, int fd3, int fd4, int fd5)
141
{
142
143
close3(fd1, fd2, fd3);
144
close2(fd4, fd5);
145
}
146
147
static int
148
my_socket(int domain, int type, int proto)
149
{
150
int sock;
151
152
sock = socket(domain, type, proto);
153
if (sock < 0)
154
err(-1, "%s: socket", test);
155
return (sock);
156
}
157
158
static void
159
my_bind(int sock, struct sockaddr *sa, socklen_t len)
160
{
161
162
if (bind(sock, sa, len) < 0)
163
err(-1, "%s: bind", test);
164
}
165
166
static void
167
my_connect(int sock, struct sockaddr *sa, socklen_t len)
168
{
169
170
if (connect(sock, sa, len) < 0 && errno != EINPROGRESS)
171
err(-1, "%s: connect", test);
172
}
173
174
static void
175
my_listen(int sock, int backlog)
176
{
177
178
if (listen(sock, backlog) < 0)
179
err(-1, "%s: listen", test);
180
}
181
182
static void
183
my_socketpair(int *sv)
184
{
185
186
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0)
187
err(-1, "%s: socketpair", test);
188
}
189
190
static void
191
my_getsockname(int s, struct sockaddr *sa, socklen_t *salen)
192
{
193
194
if (getsockname(s, sa, salen) < 0)
195
err(-1, "%s: getsockname", test);
196
}
197
198
static void
199
setnonblock(int s)
200
{
201
202
if (fcntl(s, F_SETFL, O_NONBLOCK) < 0)
203
err(-1, "%s: fcntl(F_SETFL, O_NONBLOCK)", test);
204
}
205
206
static void
207
alloc3fds(int *s, int *sv)
208
{
209
210
if ((*s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
211
err(-1, "%s: socket", test);
212
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0)
213
err(-1, "%s: socketpair", test);
214
}
215
216
static void
217
alloc5fds(int *s, int *sva, int *svb)
218
{
219
220
if ((*s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
221
err(-1, "%s: socket", test);
222
if (socketpair(PF_UNIX, SOCK_STREAM, 0, sva) < 0)
223
err(-1, "%s: socketpair", test);
224
if (socketpair(PF_UNIX, SOCK_STREAM, 0, svb) < 0)
225
err(-1, "%s: socketpair", test);
226
}
227
228
static void
229
save_sysctls(int *before_inflight, int *before_openfiles)
230
{
231
232
*before_inflight = getinflight();
233
*before_openfiles = getopenfiles();
234
}
235
236
/*
237
* Try hard to make sure that the GC does in fact run before we test the
238
* condition of things.
239
*/
240
static void
241
trigger_gc(void)
242
{
243
int s;
244
245
if (forcegc) {
246
if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
247
err(-1, "trigger_gc: socket");
248
close(s);
249
}
250
sleep(1);
251
}
252
253
static void
254
test_sysctls(int before_inflight, int before_openfiles)
255
{
256
int after_inflight, after_openfiles;
257
258
trigger_gc();
259
after_inflight = getinflight();
260
if (after_inflight != before_inflight)
261
warnx("%s: before inflight: %d, after inflight: %d",
262
test, before_inflight, after_inflight);
263
264
after_openfiles = getopenfiles();
265
if (after_openfiles != before_openfiles)
266
warnx("%s: before: %d, after: %d", test, before_openfiles,
267
after_openfiles);
268
}
269
270
static void
271
twosome_nothing(void)
272
{
273
int inflight, openfiles;
274
int sv[2];
275
276
/*
277
* Create a pair, close in one order.
278
*/
279
test = "twosome_nothing1";
280
printf("%s\n", test);
281
save_sysctls(&inflight, &openfiles);
282
my_socketpair(sv);
283
close2(sv[0], sv[1]);
284
test_sysctls(inflight, openfiles);
285
286
/*
287
* Create a pair, close in the other order.
288
*/
289
test = "twosome_nothing2";
290
printf("%s\n", test);
291
save_sysctls(&inflight, &openfiles);
292
my_socketpair(sv);
293
close2(sv[0], sv[1]);
294
test_sysctls(inflight, openfiles);
295
}
296
297
/*
298
* Using a socket pair, send various endpoints over the pair and close in
299
* various orders.
300
*/
301
static void
302
twosome_drop_work(const char *testname, int sendvia, int tosend, int closefirst)
303
{
304
int inflight, openfiles;
305
int sv[2];
306
307
printf("%s\n", testname);
308
test = testname;
309
save_sysctls(&inflight, &openfiles);
310
my_socketpair(sv);
311
sendfd(sv[sendvia], sv[tosend]);
312
if (closefirst == 0)
313
close2(sv[0], sv[1]);
314
else
315
close2(sv[1], sv[0]);
316
test_sysctls(inflight, openfiles);
317
}
318
319
static void
320
twosome_drop(void)
321
{
322
323
/*
324
* In various combations, some wastefully symmetric, create socket
325
* pairs and send one or another endpoint over one or another
326
* endpoint, closing the endpoints in various orders.
327
*/
328
twosome_drop_work("twosome_drop1", 0, 0, 0);
329
twosome_drop_work("twosome_drop2", 0, 0, 1);
330
twosome_drop_work("twosome_drop3", 0, 1, 0);
331
twosome_drop_work("twosome_drop4", 0, 1, 1);
332
twosome_drop_work("twosome_drop5", 1, 0, 0);
333
twosome_drop_work("twosome_drop6", 1, 0, 1);
334
twosome_drop_work("twosome_drop7", 1, 1, 0);
335
twosome_drop_work("twosome_drop8", 1, 1, 1);
336
}
337
338
static void
339
threesome_nothing(void)
340
{
341
int inflight, openfiles;
342
int s, sv[2];
343
344
test = "threesome_nothing";
345
printf("%s\n", test);
346
save_sysctls(&inflight, &openfiles);
347
alloc3fds(&s, sv);
348
close3(s, sv[0], sv[1]);
349
test_sysctls(inflight, openfiles);
350
}
351
352
/*
353
* threesome_drop: create a pair and a spare, send the spare over the pair, and
354
* close in various orders and make sure all the fds went away.
355
*/
356
static void
357
threesome_drop(void)
358
{
359
int inflight, openfiles;
360
int s, sv[2];
361
362
/*
363
* threesome_drop1: close sent send receive
364
*/
365
test = "threesome_drop1";
366
printf("%s\n", test);
367
save_sysctls(&inflight, &openfiles);
368
alloc3fds(&s, sv);
369
sendfd(sv[0], s);
370
close3(s, sv[0], sv[1]);
371
test_sysctls(inflight, openfiles);
372
373
/*
374
* threesome_drop2: close sent receive send
375
*/
376
test = "threesome_drop2";
377
printf("%s\n", test);
378
save_sysctls(&inflight, &openfiles);
379
alloc3fds(&s, sv);
380
sendfd(sv[0], s);
381
close3(s, sv[1], sv[0]);
382
test_sysctls(inflight, openfiles);
383
384
/*
385
* threesome_drop3: close receive sent send
386
*/
387
test = "threesome_drop3";
388
printf("%s\n", test);
389
save_sysctls(&inflight, &openfiles);
390
alloc3fds(&s, sv);
391
sendfd(sv[0], s);
392
close3(sv[1], s, sv[0]);
393
test_sysctls(inflight, openfiles);
394
395
/*
396
* threesome_drop4: close receive send sent
397
*/
398
test = "threesome_drop4";
399
printf("%s\n", test);
400
save_sysctls(&inflight, &openfiles);
401
alloc3fds(&s, sv);
402
sendfd(sv[0], s);
403
close3(sv[1], sv[0], s);
404
test_sysctls(inflight, openfiles);
405
406
/*
407
* threesome_drop5: close send receive sent
408
*/
409
test = "threesome_drop5";
410
printf("%s\n", test);
411
save_sysctls(&inflight, &openfiles);
412
alloc3fds(&s, sv);
413
sendfd(sv[0], s);
414
close3(sv[0], sv[1], s);
415
test_sysctls(inflight, openfiles);
416
417
/*
418
* threesome_drop6: close send sent receive
419
*/
420
test = "threesome_drop6";
421
printf("%s\n", test);
422
save_sysctls(&inflight, &openfiles);
423
alloc3fds(&s, sv);
424
close3(sv[0], s, sv[1]);
425
test_sysctls(inflight, openfiles);
426
}
427
428
/*
429
* Fivesome tests: create two socket pairs and a spare, send the spare over
430
* the first socket pair, then send the first socket pair over the second
431
* socket pair, and GC. Do various closes at various points to exercise
432
* various cases.
433
*/
434
static void
435
fivesome_nothing(void)
436
{
437
int inflight, openfiles;
438
int spare, sva[2], svb[2];
439
440
test = "fivesome_nothing";
441
printf("%s\n", test);
442
save_sysctls(&inflight, &openfiles);
443
alloc5fds(&spare, sva, svb);
444
close5(spare, sva[0], sva[1], svb[0], svb[1]);
445
test_sysctls(inflight, openfiles);
446
}
447
448
static void
449
fivesome_drop_work(const char *testname, int close_spare_after_send,
450
int close_sva_after_send)
451
{
452
int inflight, openfiles;
453
int spare, sva[2], svb[2];
454
455
printf("%s\n", testname);
456
test = testname;
457
save_sysctls(&inflight, &openfiles);
458
alloc5fds(&spare, sva, svb);
459
460
/*
461
* Send spare over sva.
462
*/
463
sendfd(sva[0], spare);
464
if (close_spare_after_send)
465
close(spare);
466
467
/*
468
* Send sva over svb.
469
*/
470
sendfd(svb[0], sva[0]);
471
sendfd(svb[0], sva[1]);
472
if (close_sva_after_send)
473
close2(sva[0], sva[1]);
474
475
close2(svb[0], svb[1]);
476
477
if (!close_sva_after_send)
478
close2(sva[0], sva[1]);
479
if (!close_spare_after_send)
480
close(spare);
481
482
test_sysctls(inflight, openfiles);
483
}
484
485
static void
486
fivesome_drop(void)
487
{
488
489
fivesome_drop_work("fivesome_drop1", 0, 0);
490
fivesome_drop_work("fivesome_drop2", 0, 1);
491
fivesome_drop_work("fivesome_drop3", 1, 0);
492
fivesome_drop_work("fivesome_drop4", 1, 1);
493
}
494
495
/*
496
* Create a somewhat nasty dual-socket socket intended to upset the garbage
497
* collector if mark-and-sweep is wrong.
498
*/
499
static void
500
complex_cycles(void)
501
{
502
int inflight, openfiles;
503
int spare, sva[2], svb[2];
504
505
test = "complex_cycles";
506
printf("%s\n", test);
507
save_sysctls(&inflight, &openfiles);
508
alloc5fds(&spare, sva, svb);
509
sendfd(sva[0], svb[0]);
510
sendfd(sva[0], svb[1]);
511
sendfd(svb[0], sva[0]);
512
sendfd(svb[0], sva[1]);
513
sendfd(svb[0], spare);
514
sendfd(sva[0], spare);
515
close5(spare, sva[0], sva[1], svb[0], svb[1]);
516
test_sysctls(inflight, openfiles);
517
}
518
519
/*
520
* Listen sockets can also be passed over UNIX domain sockets, so test
521
* various cases, including ones where listen sockets have waiting sockets
522
* hanging off them...
523
*/
524
static void
525
listen_nothing(void)
526
{
527
struct sockaddr_un sun;
528
struct sockaddr_in sin;
529
int inflight, openfiles;
530
int s;
531
532
test = "listen_nothing_unp";
533
printf("%s\n", test);
534
bzero(&sun, sizeof(sun));
535
sun.sun_family = AF_LOCAL;
536
sun.sun_len = sizeof(sun);
537
snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test);
538
save_sysctls(&inflight, &openfiles);
539
s = my_socket(PF_LOCAL, SOCK_STREAM, 0);
540
my_bind(s, (struct sockaddr *)&sun, sizeof(sun));
541
my_listen(s, -1);
542
close(s);
543
(void)unlink(sun.sun_path);
544
test_sysctls(inflight, openfiles);
545
546
test = "listen_nothing_inet";
547
printf("%s\n", test);
548
bzero(&sin, sizeof(sin));
549
sin.sin_family = AF_INET;
550
sin.sin_len = sizeof(sin);
551
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
552
sin.sin_port = htons(0);
553
save_sysctls(&inflight, &openfiles);
554
s = my_socket(PF_INET, SOCK_STREAM, 0);
555
my_bind(s, (struct sockaddr *)&sin, sizeof(sin));
556
my_listen(s, -1);
557
close(s);
558
test_sysctls(inflight, openfiles);
559
}
560
561
/*
562
* Send a listen UDP socket over a UNIX domain socket.
563
*
564
* Send a listen TCP socket over a UNIX domain socket.
565
*
566
* Do each twice, with closing of the listen socket vs. socketpair in
567
* different orders.
568
*/
569
static void
570
listen_drop(void)
571
{
572
struct sockaddr_un sun;
573
struct sockaddr_in sin;
574
int inflight, openfiles;
575
int s, sv[2];
576
577
bzero(&sun, sizeof(sun));
578
sun.sun_family = AF_LOCAL;
579
sun.sun_len = sizeof(sun);
580
581
/*
582
* Close listen socket first.
583
*/
584
test = "listen_drop_unp1";
585
printf("%s\n", test);
586
snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test);
587
save_sysctls(&inflight, &openfiles);
588
s = my_socket(PF_LOCAL, SOCK_STREAM, 0);
589
my_bind(s, (struct sockaddr *)&sun, sizeof(sun));
590
my_listen(s, -1);
591
my_socketpair(sv);
592
sendfd(sv[0], s);
593
close3(s, sv[0], sv[1]);
594
test_sysctls(inflight, openfiles);
595
596
/*
597
* Close socketpair first.
598
*/
599
test = "listen_drop_unp2";
600
printf("%s\n", test);
601
snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test);
602
save_sysctls(&inflight, &openfiles);
603
s = my_socket(PF_LOCAL, SOCK_STREAM, 0);
604
my_bind(s, (struct sockaddr *)&sun, sizeof(sun));
605
my_listen(s, -1);
606
my_socketpair(sv);
607
sendfd(sv[0], s);
608
close3(sv[0], sv[1], s);
609
test_sysctls(inflight, openfiles);
610
611
sin.sin_family = AF_INET;
612
sin.sin_len = sizeof(sin);
613
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
614
sin.sin_port = htons(0);
615
616
/*
617
* Close listen socket first.
618
*/
619
test = "listen_drop_inet1";
620
printf("%s\n", test);
621
bzero(&sun, sizeof(sun));
622
save_sysctls(&inflight, &openfiles);
623
s = my_socket(PF_INET, SOCK_STREAM, 0);
624
my_bind(s, (struct sockaddr *)&sin, sizeof(sin));
625
my_listen(s, -1);
626
my_socketpair(sv);
627
sendfd(sv[0], s);
628
close3(s, sv[0], sv[1]);
629
test_sysctls(inflight, openfiles);
630
631
/*
632
* Close socketpair first.
633
*/
634
test = "listen_drop_inet2";
635
printf("%s\n", test);
636
bzero(&sun, sizeof(sun));
637
save_sysctls(&inflight, &openfiles);
638
s = my_socket(PF_INET, SOCK_STREAM, 0);
639
my_bind(s, (struct sockaddr *)&sin, sizeof(sin));
640
my_listen(s, -1);
641
my_socketpair(sv);
642
sendfd(sv[0], s);
643
close3(sv[0], sv[1], s);
644
test_sysctls(inflight, openfiles);
645
}
646
647
/*
648
* Up things a notch with listen sockets: add connections that can be
649
* accepted to the listen queues.
650
*/
651
static void
652
listen_connect_nothing(void)
653
{
654
struct sockaddr_in sin;
655
int slisten, sconnect, sv[2];
656
int inflight, openfiles;
657
socklen_t len;
658
659
test = "listen_connect_nothing";
660
printf("%s\n", test);
661
save_sysctls(&inflight, &openfiles);
662
663
slisten = my_socket(PF_INET, SOCK_STREAM, 0);
664
my_bind(slisten, (struct sockaddr *)&sin, sizeof(sin));
665
my_listen(slisten, -1);
666
667
my_socketpair(sv);
668
669
len = sizeof(sin);
670
my_getsockname(slisten, (struct sockaddr *)&sin, &len);
671
672
sconnect = my_socket(PF_INET, SOCK_STREAM, 0);
673
setnonblock(sconnect);
674
my_connect(sconnect, (struct sockaddr *)&sin, len);
675
676
sleep(1);
677
678
close4(slisten, sconnect, sv[0], sv[1]);
679
680
test_sysctls(inflight, openfiles);
681
}
682
683
static void
684
listen_connect_drop(void)
685
{
686
struct sockaddr_in sin;
687
int slisten, sconnect, sv[2];
688
int inflight, openfiles;
689
socklen_t len;
690
691
test = "listen_connect_drop";
692
printf("%s\n", test);
693
save_sysctls(&inflight, &openfiles);
694
695
slisten = my_socket(PF_INET, SOCK_STREAM, 0);
696
my_bind(slisten, (struct sockaddr *)&sin, sizeof(sin));
697
my_listen(slisten, -1);
698
699
my_socketpair(sv);
700
701
len = sizeof(sin);
702
my_getsockname(slisten, (struct sockaddr *)&sin, &len);
703
704
sconnect = my_socket(PF_INET, SOCK_STREAM, 0);
705
setnonblock(sconnect);
706
my_connect(sconnect, (struct sockaddr *)&sin, len);
707
708
sleep(1);
709
sendfd(sv[0], slisten);
710
close3(slisten, sv[0], sv[1]);
711
sleep(1);
712
close(sconnect);
713
714
test_sysctls(inflight, openfiles);
715
}
716
717
static void
718
recursion(void)
719
{
720
int fd[2], ff[2];
721
int inflight, openfiles, deferred, deferred1;
722
723
test = "recursion";
724
printf("%s\n", test);
725
save_sysctls(&inflight, &openfiles);
726
deferred = getdeferred();
727
728
my_socketpair(fd);
729
730
for (;;) {
731
if (socketpair(PF_UNIX, SOCK_STREAM, 0, ff) == -1) {
732
if (errno == EMFILE || errno == ENFILE)
733
break;
734
err(-1, "socketpair");
735
}
736
sendfd(ff[0], fd[0]);
737
sendfd(ff[0], fd[1]);
738
close2(fd[1], fd[0]);
739
fd[0] = ff[0];
740
fd[1] = ff[1];
741
}
742
close2(fd[0], fd[1]);
743
sleep(1);
744
test_sysctls(inflight, openfiles);
745
deferred1 = getdeferred();
746
if (deferred != deferred1)
747
errx(-1, "recursion: deferred before %d after %d", deferred,
748
deferred1);
749
}
750
751
#define RMDIR "rm -Rf "
752
int
753
main(void)
754
{
755
char cmd[sizeof(RMDIR) + PATH_MAX];
756
int serrno;
757
pid_t pid;
758
759
strlcpy(dpath, "/tmp/unpgc.XXXXXXXX", sizeof(dpath));
760
if (mkdtemp(dpath) == NULL)
761
err(-1, "mkdtemp");
762
763
/*
764
* Set up a parent process to GC temporary storage when we're done.
765
*/
766
pid = fork();
767
if (pid < 0) {
768
serrno = errno;
769
(void)rmdir(dpath);
770
errno = serrno;
771
err(-1, "fork");
772
}
773
if (pid > 0) {
774
signal(SIGINT, SIG_IGN);
775
while (waitpid(pid, NULL, 0) != pid);
776
snprintf(cmd, sizeof(cmd), "%s %s", RMDIR, dpath);
777
(void)system(cmd);
778
exit(0);
779
}
780
781
printf("Start: inflight %d open %d\n", getinflight(),
782
getopenfiles());
783
784
twosome_nothing();
785
twosome_drop();
786
787
threesome_nothing();
788
threesome_drop();
789
790
fivesome_nothing();
791
fivesome_drop();
792
793
complex_cycles();
794
795
listen_nothing();
796
listen_drop();
797
798
listen_connect_nothing();
799
listen_connect_drop();
800
801
recursion();
802
803
printf("Finish: inflight %d open %d\n", getinflight(),
804
getopenfiles());
805
return (0);
806
}
807
808