diff --git a/changelogs/unreleased/gh-8083-fatal-signal-handler.md b/changelogs/unreleased/gh-8083-fatal-signal-handler.md
new file mode 100644
index 0000000000000000000000000000000000000000..86fb63db638b2b379cecb1d89a5f8e00dbe50e19
--- /dev/null
+++ b/changelogs/unreleased/gh-8083-fatal-signal-handler.md
@@ -0,0 +1,5 @@
+## bugfix/core
+
+* Fixed Tarantool being stuck during a crash on macOS (gh-8023).
+
+* Fixed a bug that prevents crash report being collected (gh-8083).
diff --git a/src/lib/core/errinj.h b/src/lib/core/errinj.h
index 6861b9c5d6ca636a51efe1af8011f5390d25aedf..6606f651d7b5fc5bad14578694e235ec0fb9af7f 100644
--- a/src/lib/core/errinj.h
+++ b/src/lib/core/errinj.h
@@ -119,6 +119,7 @@ struct errinj {
 	_(ERRINJ_REPLICASET_VCLOCK, ERRINJ_BOOL, {.bparam = false}) \
 	_(ERRINJ_REPLICA_JOIN_DELAY, ERRINJ_BOOL, {.bparam = false}) \
 	_(ERRINJ_SIGILL_MAIN_THREAD, ERRINJ_BOOL, {.bparam = false}) \
+	_(ERRINJ_SIGILL_NONMAIN_THREAD, ERRINJ_BOOL, {.bparam = false}) \
 	_(ERRINJ_SIO_READ_MAX, ERRINJ_INT, {.iparam = -1}) \
 	_(ERRINJ_SNAP_COMMIT_DELAY, ERRINJ_BOOL, {.bparam = false}) \
 	_(ERRINJ_SNAP_COMMIT_FAIL, ERRINJ_BOOL, {.bparam = false}) \
diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c
index 2a6dc541cb30bdab0c4ea7dcc3b40b8cfbc52bc8..2159d8048d8b35fab083d8691917a45e5484b0f0 100644
--- a/src/lib/core/fiber.c
+++ b/src/lib/core/fiber.c
@@ -1732,6 +1732,7 @@ void *cord_thread_func(void *p)
 	ct_arg->is_started = true;
 	tt_pthread_cond_signal(&ct_arg->start_cond);
 	tt_pthread_mutex_unlock(&ct_arg->start_mutex);
+	ERROR_INJECT_SIGILL(ERRINJ_SIGILL_NONMAIN_THREAD);
 	void *res = f(arg);
 	/*
 	 * cord()->on_exit initially holds NULL. This field is
diff --git a/src/tt_pthread.h b/src/tt_pthread.h
index 70f6050912010bcaf0da5ce27a1ea6093dbc9762..39c863a985bd65a2320ba29b7a49d44476e9be9c 100644
--- a/src/tt_pthread.h
+++ b/src/tt_pthread.h
@@ -264,12 +264,18 @@
 	tt_pthread_error(e__);			\
 })
 
-/** Make sure the created thread blocks all signals,
- * they are handled in the main thread.
+/**
+ * Make sure the created thread blocks all signals, they are handled in the main
+ * thread. Except SIGILL, SIGBUS, SIGFPE and SIGSEGV, that cannot be blocked and
+ * are handled by the thread that triggered them (see crash_signal_init).
  */
 #define tt_pthread_create(thread, attr, run, arg)	\
 ({	sigset_t set, oldset;				\
 	sigfillset(&set);				\
+	sigdelset(&set, SIGILL);			\
+	sigdelset(&set, SIGBUS);			\
+	sigdelset(&set, SIGFPE);			\
+	sigdelset(&set, SIGSEGV);			\
 	pthread_sigmask(SIG_BLOCK, &set, &oldset);	\
 	int e__ = pthread_create(thread, attr, run, arg);\
 	pthread_sigmask(SIG_SETMASK, &oldset, NULL);	\
diff --git a/test/app-luatest/gh_8083_fatal_signal_handler_test.lua b/test/app-luatest/gh_8083_fatal_signal_handler_test.lua
index b7b2f0db189fe35c2a24bffac0f7852ac179ad3c..8e401ea71d9cf6f68882fda317d50a79662ee2c0 100644
--- a/test/app-luatest/gh_8083_fatal_signal_handler_test.lua
+++ b/test/app-luatest/gh_8083_fatal_signal_handler_test.lua
@@ -1,5 +1,6 @@
 local t = require('luatest')
-local g = t.group('gh-8083', {{errinj = 'ERRINJ_SIGILL_MAIN_THREAD'}})
+local g = t.group('gh-8083', {{errinj = 'ERRINJ_SIGILL_MAIN_THREAD'},
+                              {errinj = 'ERRINJ_SIGILL_NONMAIN_THREAD'}})
 
 g.before_each(function(cg)
     local server = require('luatest.server')
diff --git a/test/box/errinj.result b/test/box/errinj.result
index b4d7982f413bdc5808df1de4626ef0fecdaf8f54..316462b75189f58f84ca4fdf256d99ebaeaea868 100644
--- a/test/box/errinj.result
+++ b/test/box/errinj.result
@@ -94,6 +94,7 @@ evals
   - ERRINJ_REPLICASET_VCLOCK: false
   - ERRINJ_REPLICA_JOIN_DELAY: false
   - ERRINJ_SIGILL_MAIN_THREAD: false
+  - ERRINJ_SIGILL_NONMAIN_THREAD: false
   - ERRINJ_SIO_READ_MAX: -1
   - ERRINJ_SNAP_COMMIT_DELAY: false
   - ERRINJ_SNAP_COMMIT_FAIL: false