diff --git a/tests/general/sigabrt.c b/tests/general/sigabrt.c
new file mode 100644
index 000000000..22569be4f
--- /dev/null
+++ b/tests/general/sigabrt.c
@@ -0,0 +1,10 @@
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(void) {
+    fprintf(stderr, "raising SIGABRT...\n");
+    raise(SIGABRT);
+    fprintf(stderr, "oops!\n");
+    return EXIT_FAILURE;
+}
diff --git a/tests/general/sigabrt.c.exit_status.expected b/tests/general/sigabrt.c.exit_status.expected
new file mode 100644
index 000000000..405e2afe8
--- /dev/null
+++ b/tests/general/sigabrt.c.exit_status.expected
@@ -0,0 +1 @@
+134
diff --git a/tests/general/sigabrt.c.options b/tests/general/sigabrt.c.options
new file mode 100644
index 000000000..4f07a3ec6
--- /dev/null
+++ b/tests/general/sigabrt.c.options
@@ -0,0 +1 @@
+-D_WASI_EMULATED_SIGNAL -lwasi-emulated-signal
diff --git a/tests/general/sigabrt.c.stderr.expected b/tests/general/sigabrt.c.stderr.expected
new file mode 100644
index 000000000..edba63e85
--- /dev/null
+++ b/tests/general/sigabrt.c.stderr.expected
@@ -0,0 +1,8 @@
+raising SIGABRT...
+Program recieved fatal signal: Aborted
+Error: failed to run main module `sigabrt.c.---.wasm`
+
+Caused by:
+    0: failed to invoke `_start`
+    1: wasm trap: unreachable, source location: @----
+       wasm backtrace:
diff --git a/tests/general/sigabrt.c.stderr.expected.filter b/tests/general/sigabrt.c.stderr.expected.filter
new file mode 100755
index 000000000..425b060c2
--- /dev/null
+++ b/tests/general/sigabrt.c.stderr.expected.filter
@@ -0,0 +1,7 @@
+#!/bin/bash
+set -euo pipefail
+
+cat \
+    | sed -e 's/main module `sigabrt\.c\.[^`]*\.wasm`/main module `sigabrt.c.---.wasm`/' \
+    | sed -e 's/source location: @[[:xdigit:]]*$/source location: @----/' \
+    | head -n 6
diff --git a/tests/general/signals.c b/tests/general/signals.c
new file mode 100644
index 000000000..27c8e9eae
--- /dev/null
+++ b/tests/general/signals.c
@@ -0,0 +1,79 @@
+#include <signal.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+// Make sure this exists.
+#include <sys/signal.h>
+
+volatile sig_atomic_t flag = 0;
+
+static void handler(int n) {
+    // This is undefined behavior by the spec, but this is just a testcase.
+    fflush(stdout);
+    printf("handler for signal %s\n", strsignal(n));
+    fflush(stdout);
+    flag = 1;
+}
+
+int main(void) {
+    // Test various raise cases that don't abort.
+    assert(raise(SIGCHLD) == 0);
+#ifdef SIGCLD
+    assert(raise(SIGCLD) == 0);
+#endif
+    assert(raise(SIGURG) == 0);
+    assert(raise(SIGWINCH) == 0);
+
+    errno = 0;
+    assert(raise(_NSIG) == -1 && errno == EINVAL);
+
+    // Test psignal.
+    psignal(SIGINT, "psignal message for SIGINT");
+
+    // Test strsignal.
+    printf("strsignal for SIGHUP: '%s'\n", strsignal(SIGHUP));
+
+    // Some signals can't be ignored.
+    errno = 0;
+    assert(signal(SIGKILL, SIG_IGN) == SIG_ERR && errno == EINVAL);
+    errno = 0;
+    assert(signal(SIGSTOP, SIG_IGN) == SIG_ERR && errno == EINVAL);
+
+    // Test that all the C-standard-required signals can be
+    // ignored with `SIG_IGN`.
+    int some_fatal_sigs[] = {
+        SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM
+    };
+    for (size_t i = 0;
+         i < sizeof(some_fatal_sigs) / sizeof(some_fatal_sigs[0]);
+         ++i)
+    {
+        int sig = some_fatal_sigs[i];
+        assert(signal(sig, SIG_IGN) == SIG_DFL);
+        raise(sig);
+        assert(signal(sig, SIG_DFL) == SIG_IGN);
+        assert(signal(sig, SIG_DFL) == SIG_DFL);
+    }
+
+    // Install a handler and invoke it.
+    printf("beginning handler test:\n");
+    assert(signal(SIGWINCH, handler) == SIG_DFL);
+    fflush(stdout);
+    assert(raise(SIGWINCH) == 0);
+    fflush(stdout);
+    assert(flag == 1);
+    printf("finished handler test\n");
+
+    // Check various API invariants.
+    assert(signal(SIGWINCH, SIG_IGN) == handler);
+    assert(raise(SIGWINCH) == 0);
+    assert(signal(SIGWINCH, SIG_DFL) == SIG_IGN);
+    assert(raise(SIGWINCH) == 0);
+    assert(signal(SIGWINCH, SIG_DFL) == SIG_DFL);
+    assert(raise(SIGWINCH) == 0);
+
+    return EXIT_SUCCESS;
+}
diff --git a/tests/general/signals.c.options b/tests/general/signals.c.options
new file mode 100644
index 000000000..4f07a3ec6
--- /dev/null
+++ b/tests/general/signals.c.options
@@ -0,0 +1 @@
+-D_WASI_EMULATED_SIGNAL -lwasi-emulated-signal
diff --git a/tests/general/signals.c.stderr.expected b/tests/general/signals.c.stderr.expected
new file mode 100644
index 000000000..f1b48ab7e
--- /dev/null
+++ b/tests/general/signals.c.stderr.expected
@@ -0,0 +1 @@
+psignal message for SIGINT: Interrupt
diff --git a/tests/general/signals.c.stdout.expected b/tests/general/signals.c.stdout.expected
new file mode 100644
index 000000000..b35f25678
--- /dev/null
+++ b/tests/general/signals.c.stdout.expected
@@ -0,0 +1,4 @@
+strsignal for SIGHUP: 'Hangup'
+beginning handler test:
+handler for signal Window changed
+finished handler test
