Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: tests/signal_handler/user_signal_test.cc

Issue 1212613002: Non-SFI mode: Add Linux asynchronous signal support (Closed) Base URL: https://chromium.googlesource.com/native_client/src/native_client.git@master
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2015 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file.
5 */
6
7 #include <pthread.h>
8 #include <semaphore.h>
9
10 #include "native_client/src/include/nacl/nacl_signal.h"
11 #include "native_client/src/include/nacl_assert.h"
12 #include "native_client/src/public/nonsfi/irt_signal_handling.h"
13 #include "native_client/src/untrusted/irt/irt.h"
14 #include "native_client/src/untrusted/nacl/nacl_irt.h"
15 #include "native_client/src/untrusted/nacl/nacl_thread.h"
16 #include "native_client/src/untrusted/pthread/pthread_types.h"
17
18 volatile int g_signal_count;
19 volatile int g_futex;
20 volatile int g_test_running;
21 int g_tid;
22 void* g_expected_tls;
23 sem_t g_sem;
24
25 /*
26 * Check that sending a signal before initializing signal support will result in
27 * an error.
28 */
29 void test_send_signal_before_init() {
30 int retval = nacl_signal_send_async_signal(0);
31 ASSERT_EQ(retval, ESRCH);
32 }
33
34 /*
35 * Check that nacl_tls_get() is signal-async-safe.
Mark Seaborn 2015/06/26 18:32:00 Nit: "async-signal-safe"
Luis Héctor Chávez 2015/07/06 23:45:00 Done.
36 */
37 void tls_get_signal_handler(NaClExceptionContext *exc) {
38 if (!g_test_running)
39 return;
40 ASSERT_EQ(nacl_tls_get(), g_expected_tls);
41 g_signal_count++;
42 sem_post(&g_sem);
Mark Seaborn 2015/06/26 18:32:00 Nit: check return value on all calls (sem_post(),
Luis Héctor Chávez 2015/07/06 23:45:00 Done.
43 }
44
45 void *tls_get_thread_func(void *arg) {
46 g_expected_tls = nacl_tls_get();
47 sem_post(&g_sem);
48 while (g_test_running) {
49 ASSERT_EQ(nacl_tls_get(), g_expected_tls);
50 }
51 return NULL;
52 }
53
54 void test_async_safe_tls_get() {
55 nacl_signal_set_handler(tls_get_signal_handler);
56
57 pthread_t tid;
58 g_signal_count = 0;
59 g_test_running = true;
60 int result = pthread_create(&tid, NULL, tls_get_thread_func, NULL);
61 ASSERT_EQ(0, result);
62
63 sem_wait(&g_sem);
64 const int kSignalCount = 1000;
65 for (int i = 0; i < kSignalCount; i++) {
66 nacl_signal_send_async_signal(tid->native_tid);
Mark Seaborn 2015/06/26 18:32:00 Using tid->native_tid here is unfortunate because
Luis Héctor Chávez 2015/07/06 23:45:00 The trick was not needed, since I need to be able
67 sem_wait(&g_sem);
68 }
69 g_test_running = false;
70 // Send a last signal to make sure any waiting syscalls get interrupted.
71 nacl_signal_send_async_signal(tid->native_tid);
72 pthread_join(tid, NULL);
73 ASSERT_EQ(g_signal_count, kSignalCount);
74 }
75
76 /*
77 * Check that both futex_wake() and futex_wait_abs() are signal-async-safe.
78 */
79 void futex_signal_handler(NaClExceptionContext *exc) {
80 if (!g_test_running)
81 return;
82 g_signal_count++;
83 sem_post(&g_sem);
84 int count = 0;
85 int retval = __libnacl_irt_futex.futex_wake(&g_futex, 1, &count);
86 ASSERT_EQ(retval, 0);
87 ASSERT_EQ(count, 0);
88 }
89
90 void *futex_thread_func(void *arg) {
91 sem_post(&g_sem);
92 while (g_test_running) {
93 int retval = __libnacl_irt_futex.futex_wait_abs(&g_futex, 0, NULL);
94 ASSERT_EQ(retval, EINTR);
95 }
96 return NULL;
97 }
98
99 void test_async_safe_futex() {
100 nacl_signal_set_handler(futex_signal_handler);
101
102 pthread_t tid;
103 g_test_running = true;
104 g_futex = 0;
105 int result = pthread_create(&tid, NULL, futex_thread_func, NULL);
106 ASSERT_EQ(0, result);
107
108 sem_wait(&g_sem);
109 g_signal_count = 0;
110 const int kSignalCount = 1000;
111 for (int i = 0; i < kSignalCount; i++) {
112 nacl_signal_send_async_signal(tid->native_tid);
113 sem_wait(&g_sem);
114 }
115 g_test_running = false;
116 // Send a last signal to make sure any waiting syscalls get interrupted.
117 nacl_signal_send_async_signal(tid->native_tid);
118 pthread_join(tid, NULL);
119 ASSERT_EQ(g_signal_count, kSignalCount);
120 }
121
122 /*
123 * Check that nacl_signal_send_async_signal() is async-signal-safe.
124 */
125 void signal_signal_handler(NaClExceptionContext *exc) {
126 if (!g_test_running)
127 return;
128 if (++g_signal_count % 2 == 1) {
129 nacl_signal_send_async_signal(g_tid);
130 sem_post(&g_sem);
131 }
132 }
133
134 void *signal_thread_func(void *arg) {
135 sem_post(&g_sem);
136 while (g_test_running) {
137 int retval = sleep(1);
138 ASSERT_EQ(retval, 1);
139 ASSERT_EQ(errno, EINTR);
140 }
141 return NULL;
142 }
143
144 void test_async_safe_signal() {
145 nacl_signal_set_handler(signal_signal_handler);
146
147 pthread_t tid;
148 g_test_running = true;
149 g_signal_count = 0;
150 int result = pthread_create(&tid, NULL, signal_thread_func, NULL);
151 ASSERT_EQ(0, result);
152 g_tid = tid->native_tid;
153
154 sem_wait(&g_sem);
155 const int kSignalCount = 1000;
156 for (int i = 0; i < kSignalCount; i++) {
157 nacl_signal_send_async_signal(g_tid);
158 sem_wait(&g_sem);
159 }
160 g_test_running = false;
161 // Send a last signal to make sure any waiting syscalls get interrupted.
162 nacl_signal_send_async_signal(g_tid);
163 pthread_join(tid, NULL);
164 ASSERT_EQ(g_signal_count, 2 * kSignalCount);
165 }
166
167 /*
168 * Check that passing 0 as |tid| to nacl_signal_send_async_signal() works and
169 * sends a signal to the main thread.
170 */
171 void main_signal_handler(NaClExceptionContext *exc) {
172 g_signal_count = 1;
173 }
174
175 void test_main_signal() {
176 nacl_signal_set_handler(main_signal_handler);
177
178 g_signal_count = 0;
179 int retval = nacl_signal_send_async_signal(0);
180 ASSERT_EQ(retval, 0);
181 ASSERT_EQ(g_signal_count, 1);
182 }
183
184 void run_test(const char *test_name, void (*test_func)(void)) {
185 printf("Running %s...\n", test_name);
186 test_func();
187 }
188
189 #define RUN_TEST(test_func) (run_test(#test_func, test_func))
190
191 int main(void) {
192 RUN_TEST(test_send_signal_before_init);
193
194 nonsfi_initialize_signal_handler();
195 sem_init(&g_sem, 0, 0);
196
197 RUN_TEST(test_async_safe_tls_get);
198 RUN_TEST(test_async_safe_futex);
199 RUN_TEST(test_async_safe_signal);
200 RUN_TEST(test_main_signal);
201
202 return 0;
203 }
OLDNEW
« tests/signal_handler/nacl.scons ('K') | « tests/signal_handler/nacl.scons ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698