Add testcase for issue 19851 about sigsetjmp and siglongjmp

https://code.google.com/p/android/issues/detail?id=19851

Change-Id: I78ab2fc6e51728aef92df110795be228c8905019
diff --git a/tests/device/issue19851-sigsetjmp/jni/Android.mk b/tests/device/issue19851-sigsetjmp/jni/Android.mk
new file mode 100644
index 0000000..eb8e177
--- /dev/null
+++ b/tests/device/issue19851-sigsetjmp/jni/Android.mk
@@ -0,0 +1,6 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := issue19851-sigsetjmp
+LOCAL_SRC_FILES := issue19851-sigsetjmp.c
+include $(BUILD_EXECUTABLE)
diff --git a/tests/device/issue19851-sigsetjmp/jni/Application.mk b/tests/device/issue19851-sigsetjmp/jni/Application.mk
new file mode 100644
index 0000000..a252a72
--- /dev/null
+++ b/tests/device/issue19851-sigsetjmp/jni/Application.mk
@@ -0,0 +1 @@
+APP_ABI := all
diff --git a/tests/device/issue19851-sigsetjmp/jni/issue19851-sigsetjmp.c b/tests/device/issue19851-sigsetjmp/jni/issue19851-sigsetjmp.c
new file mode 100644
index 0000000..49d35ee
--- /dev/null
+++ b/tests/device/issue19851-sigsetjmp/jni/issue19851-sigsetjmp.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <setjmp.h>
+
+static sigjmp_buf sbuf;
+
+void handler(int sig)
+{
+    printf("In handler()\n");
+    siglongjmp(sbuf, 99);
+    printf("After calling siglongjmp, but you won't see me here.\n");
+}
+
+void foo()
+{
+    struct sigaction sact;
+    sigset_t sset;
+    printf("In foo()\n");
+
+ /* Setup signal handler for SIGUSR2 */
+    sigemptyset(&sact.sa_mask);
+    sact.sa_flags = 0;
+    sact.sa_handler = handler;
+    sigaction(SIGUSR2, &sact, NULL);
+
+ /* Unblock SIGUSR2 */
+    sigemptyset(&sset);
+    sigaddset(&sset, SIGUSR2);
+    sigprocmask(SIG_UNBLOCK, &sset, NULL);
+
+ /* Action */
+    kill(getpid(), SIGUSR2);
+
+    printf("After calling kill, but you won't see me here.\n");
+}
+
+void bar()
+{
+    printf("In bar()\n");
+    foo();
+    printf("After calling foo, but you won't see me here.\n");
+}
+
+int main()
+{
+    int code, ret;
+    sigset_t sset;
+    printf("In main()\n");
+    sigemptyset(&sset);
+    sigaddset(&sset, SIGUSR1);
+    sigaddset(&sset, SIGUSR2);
+    sigprocmask(SIG_SETMASK, &sset, NULL);
+    if ((code = sigsetjmp(sbuf, 1)) == 0)
+    {
+        bar();
+        ret = 0xDEADBEEF;
+    }
+    else
+    {
+        printf("siglongjmp() back to main, code = %d\n", code);
+      /* Make sure SIGUSR2 still blocked */
+        sigprocmask(SIG_SETMASK, NULL, &sset);
+        ret = sigismember(&sset, SIGUSR2)? 0 : -1;
+    }
+    printf("ret = %d\n", ret);
+
+    return ret;
+}