diff --git a/src/testsuite.in b/src/testsuite.in
index dd991ceb46d739cce03705e950d1d632604c5919..cf1bc945f0eb4cb42bfec4a30db05571420bece8 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -5363,6 +5363,14 @@ void test()
     return Process.system (RUNPIKE +" testsuite_test.pike");
   ]], 0)
 
+  test_eval_error([[
+    Thread.thread_create(lambda(){
+	// NB: It's currently not possible to inhibit the
+	//     backtrace (without messing with the master).
+	error("Ignore the following line.\n");
+    })->wait();
+  ]])
+
 cond_end // thread_create
 
 cond([[0]],
diff --git a/src/threads.c b/src/threads.c
index fae2e9a5cc054d3bcb0a54ffb008a755a3a10acd..e2a528a158d48ec627f409f3142d370764626cd9 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -1784,20 +1784,26 @@ TH_RETURN_TYPE new_thread_func(void *data)
 
   if(SETJMP(back))
   {
-    if(throw_severity <= THROW_ERROR)
+    if(throw_severity <= THROW_ERROR) {
+      if (thread_state->thread_obj) {
+	/* Copy the thrown exit value to the thread_state here,
+	 * if the thread hasn't been destructed. */
+	assign_svalue(&thread_state->result, &throw_value);
+      }
+
       call_handle_error();
-    else if(throw_severity == THROW_EXIT)
+    }
+
+    if(throw_severity == THROW_EXIT)
     {
       /* This is too early to get a clean exit if DO_PIKE_CLEANUP is
        * active. Otoh it cannot be done later since it requires the
        * evaluator stacks in the gc calls. It's difficult to solve
        * without handing over the cleanup duty to the main thread. */
       pike_do_exit(throw_value.u.integer);
-    } else if (thread_state->thread_obj) {
-      /* Copy the thrown exit value to the thread_state here,
-       * if the thread hasn't been destructed. */
-      assign_svalue(&thread_state->result, &throw_value);
     }
+
+    thread_state->status = THREAD_ABORTED;
   } else {
     INT32 args=arg.args->size;
     back.severity=THROW_EXIT;
@@ -1810,6 +1816,8 @@ TH_RETURN_TYPE new_thread_func(void *data)
     if (thread_state->thread_obj)
       assign_svalue(&thread_state->result, Pike_sp-1);
     pop_stack();
+
+    thread_state->status = THREAD_EXITED;
   }
 
   UNSETJMP(back);
@@ -1821,7 +1829,6 @@ TH_RETURN_TYPE new_thread_func(void *data)
     thread_state->thread_local = NULL;
   }
 
-  thread_state->status = THREAD_EXITED;
   co_broadcast(&thread_state->status_change);
 
   THREADS_FPRINTF(0, (stderr,"new_thread_func(): Thread %p done\n",
@@ -2683,6 +2690,7 @@ void f_thread_backtrace(INT32 args)
  *!     @value Thread.THREAD_NOT_STARTED
  *!     @value Thread.THREAD_RUNNING
  *!     @value Thread.THREAD_EXITED
+ *!     @value Thread.THREAD_ABORTED
  *!   @endint
  */
 void f_thread_id_status(INT32 args)
@@ -2728,10 +2736,15 @@ void f_thread_id_id_number(INT32 args)
  *!
  *! Waits for the thread to complete, and then returns
  *! the value returned from the thread function.
+ *!
+ *! @throws
+ *!   Rethrows the error thrown by the thread if it exited by
+ *!   throwing an error.
  */
 static void f_thread_id_result(INT32 UNUSED(args))
 {
   struct thread_state *th=THIS_THREAD;
+  int th_status;
 
   if (threads_disabled) {
     Pike_error("Cannot wait for threads when threads are disabled!\n");
@@ -2741,7 +2754,7 @@ static void f_thread_id_result(INT32 UNUSED(args))
 
   THREADS_FPRINTF(0, (stderr, "Thread->wait(): Waiting for thread_state %p "
 		      "(state:%d).\n", th, th->status));
-  while(th->status != THREAD_EXITED) {
+  while(th->status < THREAD_EXITED) {
     SWAP_OUT_CURRENT_THREAD();
     co_wait_interpreter(&th->status_change);
     SWAP_IN_CURRENT_THREAD();
@@ -2751,6 +2764,8 @@ static void f_thread_id_result(INT32 UNUSED(args))
 		     "(state:%d).\n", th, th->status));
   }
 
+  th_status = th->status;
+
   assign_svalue_no_free(Pike_sp, &th->result);
   Pike_sp++;
   dmalloc_touch_svalue(Pike_sp-1);
@@ -2760,6 +2775,8 @@ static void f_thread_id_result(INT32 UNUSED(args))
   if (!th->thread_obj)
     /* Do this only if exit_thread_obj already has run. */
     cleanup_thread_state (th);
+
+  if (th_status == THREAD_ABORTED) f_throw(1);
 }
 
 static int num_pending_interrupts = 0;
@@ -3370,6 +3387,7 @@ void th_init(void)
   add_integer_constant("THREAD_NOT_STARTED", THREAD_NOT_STARTED, 0);
   add_integer_constant("THREAD_RUNNING", THREAD_RUNNING, 0);
   add_integer_constant("THREAD_EXITED", THREAD_EXITED, 0);
+  add_integer_constant("THREAD_ABORTED", THREAD_ABORTED, 0);
 
   original_interpreter = Pike_interpreter_pointer;
   backend_thread_obj = fast_clone_object(thread_id_prog);
diff --git a/src/threads.h b/src/threads.h
index 2b911e5dcfd7a6d1aaed7da3212cb19877bf2d38..4e9f8b615a5ae5af1cdb6bb77ced1bc36e785d2b 100644
--- a/src/threads.h
+++ b/src/threads.h
@@ -23,6 +23,7 @@ struct pike_frame;
 #define THREAD_NOT_STARTED -1
 #define THREAD_RUNNING 0
 #define THREAD_EXITED 1
+#define THREAD_ABORTED 2
 
 /* Thread flags */
 #define THREAD_FLAG_TERM	1	/* Pending termination. */