diff options
Diffstat (limited to 'lib/kunit/try-catch.c')
| -rw-r--r-- | lib/kunit/try-catch.c | 40 | 
1 files changed, 29 insertions, 11 deletions
| diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c index f7825991d576..6bbe0025b079 100644 --- a/lib/kunit/try-catch.c +++ b/lib/kunit/try-catch.c @@ -11,13 +11,14 @@  #include <linux/completion.h>  #include <linux/kernel.h>  #include <linux/kthread.h> +#include <linux/sched/task.h>  #include "try-catch-impl.h"  void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)  {  	try_catch->try_result = -EFAULT; -	kthread_complete_and_exit(try_catch->try_completion, -EFAULT); +	kthread_exit(0);  }  EXPORT_SYMBOL_GPL(kunit_try_catch_throw); @@ -25,9 +26,12 @@ static int kunit_generic_run_threadfn_adapter(void *data)  {  	struct kunit_try_catch *try_catch = data; +	try_catch->try_result = -EINTR;  	try_catch->try(try_catch->context); +	if (try_catch->try_result == -EINTR) +		try_catch->try_result = 0; -	kthread_complete_and_exit(try_catch->try_completion, 0); +	return 0;  }  static unsigned long kunit_test_timeout(void) @@ -57,30 +61,38 @@ static unsigned long kunit_test_timeout(void)  void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)  { -	DECLARE_COMPLETION_ONSTACK(try_completion);  	struct kunit *test = try_catch->test;  	struct task_struct *task_struct; +	struct completion *task_done;  	int exit_code, time_remaining;  	try_catch->context = context; -	try_catch->try_completion = &try_completion;  	try_catch->try_result = 0; -	task_struct = kthread_run(kunit_generic_run_threadfn_adapter, -				  try_catch, -				  "kunit_try_catch_thread"); +	task_struct = kthread_create(kunit_generic_run_threadfn_adapter, +				     try_catch, "kunit_try_catch_thread");  	if (IS_ERR(task_struct)) { +		try_catch->try_result = PTR_ERR(task_struct);  		try_catch->catch(try_catch->context);  		return;  	} +	get_task_struct(task_struct); +	/* +	 * As for a vfork(2), task_struct->vfork_done (pointing to the +	 * underlying kthread->exited) can be used to wait for the end of a +	 * kernel thread. It is set to NULL when the thread exits, so we +	 * keep a copy here. +	 */ +	task_done = task_struct->vfork_done; +	wake_up_process(task_struct); -	time_remaining = wait_for_completion_timeout(&try_completion, +	time_remaining = wait_for_completion_timeout(task_done,  						     kunit_test_timeout());  	if (time_remaining == 0) { -		kunit_err(test, "try timed out\n");  		try_catch->try_result = -ETIMEDOUT;  		kthread_stop(task_struct);  	} +	put_task_struct(task_struct);  	exit_code = try_catch->try_result;  	if (!exit_code) @@ -88,8 +100,14 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)  	if (exit_code == -EFAULT)  		try_catch->try_result = 0; -	else if (exit_code == -EINTR) -		kunit_err(test, "wake_up_process() was never called\n"); +	else if (exit_code == -EINTR) { +		if (test->last_seen.file) +			kunit_err(test, "try faulted: last line seen %s:%d\n", +				  test->last_seen.file, test->last_seen.line); +		else +			kunit_err(test, "try faulted\n"); +	} else if (exit_code == -ETIMEDOUT) +		kunit_err(test, "try timed out\n");  	else if (exit_code)  		kunit_err(test, "Unknown error: %d\n", exit_code); | 
