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

Unified 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, 6 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 side-by-side diff with in-line comments
Download patch
« tests/signal_handler/nacl.scons ('K') | « tests/signal_handler/nacl.scons ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tests/signal_handler/user_signal_test.cc
diff --git a/tests/signal_handler/user_signal_test.cc b/tests/signal_handler/user_signal_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d3c9a285058eb30e04cfa2afd1e16f02de8376da
--- /dev/null
+++ b/tests/signal_handler/user_signal_test.cc
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2015 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <pthread.h>
+#include <semaphore.h>
+
+#include "native_client/src/include/nacl/nacl_signal.h"
+#include "native_client/src/include/nacl_assert.h"
+#include "native_client/src/public/nonsfi/irt_signal_handling.h"
+#include "native_client/src/untrusted/irt/irt.h"
+#include "native_client/src/untrusted/nacl/nacl_irt.h"
+#include "native_client/src/untrusted/nacl/nacl_thread.h"
+#include "native_client/src/untrusted/pthread/pthread_types.h"
+
+volatile int g_signal_count;
+volatile int g_futex;
+volatile int g_test_running;
+int g_tid;
+void* g_expected_tls;
+sem_t g_sem;
+
+/*
+ * Check that sending a signal before initializing signal support will result in
+ * an error.
+ */
+void test_send_signal_before_init() {
+ int retval = nacl_signal_send_async_signal(0);
+ ASSERT_EQ(retval, ESRCH);
+}
+
+/*
+ * 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.
+ */
+void tls_get_signal_handler(NaClExceptionContext *exc) {
+ if (!g_test_running)
+ return;
+ ASSERT_EQ(nacl_tls_get(), g_expected_tls);
+ g_signal_count++;
+ 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.
+}
+
+void *tls_get_thread_func(void *arg) {
+ g_expected_tls = nacl_tls_get();
+ sem_post(&g_sem);
+ while (g_test_running) {
+ ASSERT_EQ(nacl_tls_get(), g_expected_tls);
+ }
+ return NULL;
+}
+
+void test_async_safe_tls_get() {
+ nacl_signal_set_handler(tls_get_signal_handler);
+
+ pthread_t tid;
+ g_signal_count = 0;
+ g_test_running = true;
+ int result = pthread_create(&tid, NULL, tls_get_thread_func, NULL);
+ ASSERT_EQ(0, result);
+
+ sem_wait(&g_sem);
+ const int kSignalCount = 1000;
+ for (int i = 0; i < kSignalCount; i++) {
+ 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
+ sem_wait(&g_sem);
+ }
+ g_test_running = false;
+ // Send a last signal to make sure any waiting syscalls get interrupted.
+ nacl_signal_send_async_signal(tid->native_tid);
+ pthread_join(tid, NULL);
+ ASSERT_EQ(g_signal_count, kSignalCount);
+}
+
+/*
+ * Check that both futex_wake() and futex_wait_abs() are signal-async-safe.
+ */
+void futex_signal_handler(NaClExceptionContext *exc) {
+ if (!g_test_running)
+ return;
+ g_signal_count++;
+ sem_post(&g_sem);
+ int count = 0;
+ int retval = __libnacl_irt_futex.futex_wake(&g_futex, 1, &count);
+ ASSERT_EQ(retval, 0);
+ ASSERT_EQ(count, 0);
+}
+
+void *futex_thread_func(void *arg) {
+ sem_post(&g_sem);
+ while (g_test_running) {
+ int retval = __libnacl_irt_futex.futex_wait_abs(&g_futex, 0, NULL);
+ ASSERT_EQ(retval, EINTR);
+ }
+ return NULL;
+}
+
+void test_async_safe_futex() {
+ nacl_signal_set_handler(futex_signal_handler);
+
+ pthread_t tid;
+ g_test_running = true;
+ g_futex = 0;
+ int result = pthread_create(&tid, NULL, futex_thread_func, NULL);
+ ASSERT_EQ(0, result);
+
+ sem_wait(&g_sem);
+ g_signal_count = 0;
+ const int kSignalCount = 1000;
+ for (int i = 0; i < kSignalCount; i++) {
+ nacl_signal_send_async_signal(tid->native_tid);
+ sem_wait(&g_sem);
+ }
+ g_test_running = false;
+ // Send a last signal to make sure any waiting syscalls get interrupted.
+ nacl_signal_send_async_signal(tid->native_tid);
+ pthread_join(tid, NULL);
+ ASSERT_EQ(g_signal_count, kSignalCount);
+}
+
+/*
+ * Check that nacl_signal_send_async_signal() is async-signal-safe.
+ */
+void signal_signal_handler(NaClExceptionContext *exc) {
+ if (!g_test_running)
+ return;
+ if (++g_signal_count % 2 == 1) {
+ nacl_signal_send_async_signal(g_tid);
+ sem_post(&g_sem);
+ }
+}
+
+void *signal_thread_func(void *arg) {
+ sem_post(&g_sem);
+ while (g_test_running) {
+ int retval = sleep(1);
+ ASSERT_EQ(retval, 1);
+ ASSERT_EQ(errno, EINTR);
+ }
+ return NULL;
+}
+
+void test_async_safe_signal() {
+ nacl_signal_set_handler(signal_signal_handler);
+
+ pthread_t tid;
+ g_test_running = true;
+ g_signal_count = 0;
+ int result = pthread_create(&tid, NULL, signal_thread_func, NULL);
+ ASSERT_EQ(0, result);
+ g_tid = tid->native_tid;
+
+ sem_wait(&g_sem);
+ const int kSignalCount = 1000;
+ for (int i = 0; i < kSignalCount; i++) {
+ nacl_signal_send_async_signal(g_tid);
+ sem_wait(&g_sem);
+ }
+ g_test_running = false;
+ // Send a last signal to make sure any waiting syscalls get interrupted.
+ nacl_signal_send_async_signal(g_tid);
+ pthread_join(tid, NULL);
+ ASSERT_EQ(g_signal_count, 2 * kSignalCount);
+}
+
+/*
+ * Check that passing 0 as |tid| to nacl_signal_send_async_signal() works and
+ * sends a signal to the main thread.
+ */
+void main_signal_handler(NaClExceptionContext *exc) {
+ g_signal_count = 1;
+}
+
+void test_main_signal() {
+ nacl_signal_set_handler(main_signal_handler);
+
+ g_signal_count = 0;
+ int retval = nacl_signal_send_async_signal(0);
+ ASSERT_EQ(retval, 0);
+ ASSERT_EQ(g_signal_count, 1);
+}
+
+void run_test(const char *test_name, void (*test_func)(void)) {
+ printf("Running %s...\n", test_name);
+ test_func();
+}
+
+#define RUN_TEST(test_func) (run_test(#test_func, test_func))
+
+int main(void) {
+ RUN_TEST(test_send_signal_before_init);
+
+ nonsfi_initialize_signal_handler();
+ sem_init(&g_sem, 0, 0);
+
+ RUN_TEST(test_async_safe_tls_get);
+ RUN_TEST(test_async_safe_futex);
+ RUN_TEST(test_async_safe_signal);
+ RUN_TEST(test_main_signal);
+
+ return 0;
+}
« 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