10 #include <ccan/tap/tap.h>
11 #include <ccan/altstack/altstack.h>
22 int fail, call1, call2;
25 #define e(x) (900+(x))
26 #define seterr(x) (errno = e(x))
27 #define setcall(x) ((call1 |= !errno ? (x) : 0), (call2 |= errno || out_ ? (x) : 0))
28 #define getrlimit(...) (fail&getrlimit_ ? (seterr(getrlimit_), -1) : (setcall(getrlimit_), getrlimit(__VA_ARGS__)))
29 #define mmap(...) (fail&mmap_ ? (seterr(mmap_), (void *)-1) : (setcall(mmap_), mmap(__VA_ARGS__)))
30 #define munmap(a, b) (fail&munmap_ ? (seterr(munmap_), -1) : (setcall(munmap_), munmap(m_=(a), msz_=(b))))
31 #define setrlimit(...) (fail&setrlimit_ ? (seterr(setrlimit_), -1) : (setcall(setrlimit_), setrlimit(__VA_ARGS__)))
32 #define sigaltstack(...) (fail&sigaltstack_ ? (seterr(sigaltstack_), -1) : (setcall(sigaltstack_), sigaltstack(__VA_ARGS__)))
33 #define sigaction(...) (fail&sigaction_ ? (seterr(sigaction_), -1) : (setcall(sigaction_), sigaction(__VA_ARGS__)))
42 #define stderr mystderr
44 #include <ccan/altstack/altstack.c>
49 static void __attribute__((optimize("O0"))) dn(unsigned long i)
51 if (used) used = altstack_used();
54 static void *wrap(void *i)
56 dn((unsigned long) i);
62 long pgsz = sysconf(_SC_PAGESIZE);
66 #define chkfail(x, y, z, c1, c2) (call1 = 0, call2 = 0, errno = 0, ok1((fail = x) && (y) && errno == (z) && call1 == (c1) && call2 == (c2)));
67 #define chkok( y, z, c1, c2) (call1 = 0, call2 = 0, errno = 0, fail = 0, ok1((y) && errno == (z) && call1 == (c1) && call2 == (c2)));
69 chkfail(getrlimit_, altstack(8*MiB, wrap, 0, 0) == -1, e(getrlimit_),
73 chkfail(setrlimit_, altstack(8*MiB, wrap, 0, 0) == -1, e(setrlimit_),
77 chkfail(mmap_, altstack(8*MiB, wrap, 0, 0) == -1, e(mmap_),
78 getrlimit_|setrlimit_,
81 chkfail(sigaltstack_, altstack(8*MiB, wrap, 0, 0) == -1, e(sigaltstack_),
82 getrlimit_|setrlimit_|mmap_,
85 chkfail(sigaction_, altstack(8*MiB, wrap, 0, 0) == -1, e(sigaction_),
86 getrlimit_|setrlimit_|mmap_|sigaltstack_,
87 setrlimit_|munmap_|sigaltstack_);
89 chkfail(munmap_, altstack(8*MiB, wrap, 0, 0) == 1, e(munmap_),
90 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
91 setrlimit_|sigaltstack_|sigaction_);
92 if (fail = 0, munmap(m_, msz_) == -1)
95 chkok( altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
96 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
97 setrlimit_|munmap_|sigaltstack_|sigaction_);
99 // be sure segv catch is repeatable (SA_NODEFER)
100 chkok( altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
101 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
102 setrlimit_|munmap_|sigaltstack_|sigaction_);
105 chkfail(munmap_, altstack(1*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
106 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
107 setrlimit_|sigaltstack_|sigaction_);
108 if (fail = 0, munmap(m_, msz_) == -1)
111 ok1(altstack_max() == 1*MiB);
112 diag("used: %lu", used);
113 ok1(used >= 1*MiB - pgsz && used <= 1*MiB + pgsz);
116 for(p = altstack_geterr(); *p; p++)
117 if (*p >= '0' && *p <= '9')
120 #define estr "(altstack@~~~) SIGSEGV caught; (altstack@~~~) munmap(m, max): Unknown error ~~~"
121 ok1(strcmp(altstack_geterr(), estr) == 0);
123 char buf[ALTSTACK_ERR_MAXLEN*2] = {0};
124 if ((mystderr = fmemopen(buf, sizeof(buf), "w")) == NULL)
129 ok1(strcmp(buf, estr "\n") == 0);
132 chkok( altstack(8*MiB, wrap, (void *) 1000000, 0) == -1, EOVERFLOW,
133 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_,
134 setrlimit_|munmap_|sigaltstack_|sigaction_);
136 diag("used: %lu", used);
137 ok1(used >= 8*MiB - pgsz && used <= 8*MiB + pgsz);
140 chkok( altstack(8*MiB, wrap, (void *) 100000, 0) == 0, 0,
141 getrlimit_|setrlimit_|mmap_|sigaltstack_|sigaction_|munmap_,
142 setrlimit_|munmap_|sigaltstack_|sigaction_);
147 diag("used: %lu", used);
148 ok1(used == 32 || used == 40);
150 return exit_status();