[1/3] xfs_repair: clear pthread_t when pthread_create fails
diff mbox

Message ID 1484627973-11535-2-git-send-email-jeffm@suse.com
State Accepted
Headers show

Commit Message

Jeff Mahoney Jan. 17, 2017, 4:39 a.m. UTC
From: Jeff Mahoney <jeffm@suse.com>

pf_queuing_worker and pf_create_prefetch_thread both try to handle
thread creation failure gracefully, but assume that pthread_create
doesn't modify the pthread_t when it fails.

From the pthread_create man page:
On  success,  pthread_create() returns 0; on error, it returns an error
number, and the contents of *thread are undefined.

In fact, glibc's pthread_create writes the pthread_t value before
calling clone().  When we join the created threads in
cleanup_inode_prefetch and the cleanup stage of pf_queuing_worker, we
assume that if the pthread_t is nonzero that it's a valid thread handle
and end up crashing in pthread_join.

This patch zeros out the handle after pthread_create failure.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 repair/prefetch.c | 2 ++
 1 file changed, 2 insertions(+)

Comments

Eric Sandeen June 15, 2017, 7:11 p.m. UTC | #1
On 1/16/17 10:39 PM, jeffm@suse.com wrote:
> From: Jeff Mahoney <jeffm@suse.com>
> 
> pf_queuing_worker and pf_create_prefetch_thread both try to handle
> thread creation failure gracefully, but assume that pthread_create
> doesn't modify the pthread_t when it fails.
> 
> From the pthread_create man page:
> On  success,  pthread_create() returns 0; on error, it returns an error
> number, and the contents of *thread are undefined.
> 
> In fact, glibc's pthread_create writes the pthread_t value before
> calling clone().  When we join the created threads in
> cleanup_inode_prefetch and the cleanup stage of pf_queuing_worker, we
> assume that if the pthread_t is nonzero that it's a valid thread handle
> and end up crashing in pthread_join.
> 
> This patch zeros out the handle after pthread_create failure.
> 
> Signed-off-by: Jeff Mahoney <jeffm@suse.com>

Sweeping up old patches, sorry for missing these.

Reviewed-by: Eric Sandeen <sandeen@redhat.com>

> ---
>  repair/prefetch.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/repair/prefetch.c b/repair/prefetch.c
> index ff50606..044fab2 100644
> --- a/repair/prefetch.c
> +++ b/repair/prefetch.c
> @@ -703,6 +703,7 @@ pf_queuing_worker(
>  		if (err != 0) {
>  			do_warn(_("failed to create prefetch thread: %s\n"),
>  				strerror(err));
> +			args->io_threads[i] = 0;
>  			if (i == 0) {
>  				pf_start_processing(args);
>  				return NULL;
> @@ -816,6 +817,7 @@ pf_create_prefetch_thread(
>  	if (err != 0) {
>  		do_warn(_("failed to create prefetch thread: %s\n"),
>  			strerror(err));
> +		args->queuing_thread = 0;
>  		cleanup_inode_prefetch(args);
>  	}
>  
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-xfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch
diff mbox

diff --git a/repair/prefetch.c b/repair/prefetch.c
index ff50606..044fab2 100644
--- a/repair/prefetch.c
+++ b/repair/prefetch.c
@@ -703,6 +703,7 @@  pf_queuing_worker(
 		if (err != 0) {
 			do_warn(_("failed to create prefetch thread: %s\n"),
 				strerror(err));
+			args->io_threads[i] = 0;
 			if (i == 0) {
 				pf_start_processing(args);
 				return NULL;
@@ -816,6 +817,7 @@  pf_create_prefetch_thread(
 	if (err != 0) {
 		do_warn(_("failed to create prefetch thread: %s\n"),
 			strerror(err));
+		args->queuing_thread = 0;
 		cleanup_inode_prefetch(args);
 	}