8 #include <ccan/tap/tap.h>
9 #include <ccan/altstack/altstack.h>
10 #define _XOPEN_SOURCE 700
21 int fail, call1, call2;
24 #define e(x) (900+(x))
25 #define seterr(x) (errno = e(x))
26 #define setcall(x) ((call1 |= !errno ? (x) : 0), (call2 |= errno || out_ ? (x) : 0))
27 #define getrlimit(...) (fail&getrlimit_ ? (seterr(getrlimit_), -1) : (setcall(getrlimit_), getrlimit(__VA_ARGS__)))
28 #define mmap(...) (fail&mmap_ ? (seterr(mmap_), (void *)-1) : (setcall(mmap_), mmap(__VA_ARGS__)))
29 #define munmap(a, b) (fail&munmap_ ? (seterr(munmap_), -1) : (setcall(munmap_), munmap(m_=(a), max_=(b))))
30 #define setrlimit(...) (fail&setrlimit_ ? (seterr(setrlimit_), -1) : (setcall(setrlimit_), setrlimit(__VA_ARGS__)))
31 #define sigaltstack(...) (fail&sigaltstack_ ? (seterr(sigaltstack_), -1) : (setcall(sigaltstack_), sigaltstack(__VA_ARGS__)))
32 #define sigaction(...) (fail&sigaction_ ? (seterr(sigaction_), -1) : (setcall(sigaction_), sigaction(__VA_ARGS__)))
41 #define stderr mystderr
43 #include <ccan/altstack/altstack.c>
48 static void __attribute__((optimize("O0"))) dn(unsigned long i)
50 if (used) used = altstack_used();
53 static void *wrap(void *i)
55 dn((unsigned long) i);
63 #define chkfail(x, y, z, c1, c2) (call1 = 0, call2 = 0, errno = 0, ok1((fail = x) && (y) && errno == (z) && call1 == (c1) && call2 == (c2)));
64 #define chkok( y, z, c1, c2) (call1 = 0, call2 = 0, errno = 0, fail = 0, ok1((y) && errno == (z) && call1 == (c1) && call2 == (c2)));
66 chkfail(getrlimit_, altstack(8*MiB, wrap, 0, 0) == -1, e(getrlimit_),
70 chkfail(setrlimit_, altstack(8*MiB, wrap, 0, 0) == -1, e(setrlimit_),
74 chkfail(mmap_, altstack(8*MiB, wrap, 0, 0) == -1, e(mmap_),
75 getrlimit_|setrlimit_,
78 chkfail(sigaltstack_, altstack(8*MiB, wrap, 0, 0) == -1, e(sigaltstack_),
79 getrlimit_|setrlimit_|mmap_,
82 chkfail(sigaction_, altstack(8*MiB, wrap, 0, 0) == -1, e(sigaction_),
83 getrlimit_|setrlimit_|mmap_|sigaltstack_,
84 setrlimit_|munmap_|sigaltstack_);
86 chkfail(munmap_, altstack(8*MiB, wrap, 0, 0) == 1, e(munmap_),
87 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
88 setrlimit_|sigaltstack_|sigaction_);
89 if (fail = 0, munmap(m_, max_) == -1)
92 chkok( altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
93 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
94 setrlimit_|munmap_|sigaltstack_|sigaction_);
96 // be sure segv catch is repeatable (SA_NODEFER)
97 chkok( altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
98 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
99 setrlimit_|munmap_|sigaltstack_|sigaction_);
102 chkfail(munmap_, altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
103 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
104 setrlimit_|sigaltstack_|sigaction_);
105 if (fail = 0, munmap(m_, max_) == -1)
108 ok1(used > 1*MiB-1*KiB && used < 1*MiB);
111 for(p = altstack_geterr(); *p; p++)
112 if (*p >= '0' && *p <= '9')
115 #define estr "(altstack@~~~) SIGSEGV caught; (altstack@~~~) munmap(m, max): Unknown error ~~~"
116 ok1(strcmp(altstack_geterr(), estr) == 0);
118 char buf[ALTSTACK_ERR_MAXLEN*2] = {0};
119 if ((mystderr = fmemopen(buf, sizeof(buf), "w")) == NULL)
124 ok1(strcmp(buf, estr "\n") == 0);
127 chkok( altstack(8*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
128 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
129 setrlimit_|munmap_|sigaltstack_|sigaction_);
131 ok1(used > 8*MiB-8*KiB && used < 8*MiB);
134 chkok( altstack(8*MiB, wrap, (void *) 100000, 0) == 0, 0,
135 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_|munmap_,
136 setrlimit_|munmap_|sigaltstack_|sigaction_);
143 return exit_status();