Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 May 2002 18:30:41 -0700 (PDT)
From:      Archie Cobbs <archie@packetdesign.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/37658: libc_r: poll(2) does not wake up when thread canceled
Message-ID:  <200205020130.g421UfB04028@bubba.packetdesign.com>

next in thread | raw e-mail | index | archive | help

>Number:         37658
>Category:       bin
>Synopsis:       libc_r: poll(2) does not wake up when thread canceled
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed May 01 18:40:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Archie Cobbs
>Release:        FreeBSD 4.5-RELEASE i386
>Organization:
Packet Design
>Environment:
System: FreeBSD bubba.packetdesign.com 4.5-RELEASE FreeBSD 4.5-RELEASE #0: Sun Feb 3 10:00:07 PST 2002 archie@bubba.packetdesign.com:/usr/obj/usr/src/sys/BUBBA i386

>Description:

	Have a thread block in poll(2), which is a cancellation point.
	Have another thread cancel that thread with pthread_cancel().

	Problem: the cancellation does not take effect until the
	poll(2) returns, which can be arbitrarily long in the future
	or even never!

>How-To-Repeat:

Run this program - it should exit in 2 seconds, but it actually takes 4

---------------------------------------------------------------------------

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sched.h>
#include <pthread.h>
#include <poll.h>
#include <err.h>

#define MAIN_WAIT	2
#define THREAD_WAIT	4

static void
thread_final(void *arg)
{
	printf("Thread: exiting...\n");
}

static void *
thread_main(void *arg)
{
	struct pollfd pfd;

	pthread_cleanup_push(thread_final, NULL);
	memset(&pfd, 0, sizeof(pfd));
	pfd.fd = 0;
	pfd.events = POLLERR;
	printf("Thread: polling for %d seconds...\n", THREAD_WAIT);
	if (poll(&pfd, 1, THREAD_WAIT * 1000) == -1)
		err(1, "poll");
	return (NULL);
}

int
main(int argc, char **argv)
{
	pthread_t tid;

	printf("
Demonstration of bug in poll(2) where canceling a thread
doesn't immediately wake it up from a poll(2).

");

	/* Spawn thread */
	printf("Main: spawning thread...\n");
	if ((errno = pthread_create(&tid, NULL, thread_main, NULL)) != 0)
		err(1, "pthread_create");

	/* Pause */
	printf("Main: sleeping %d seconds...\n", MAIN_WAIT);
	sleep(MAIN_WAIT);

	/* Cancel thread */
	printf("Main: canceling thread...\n");
	pthread_cancel(tid);
	printf("Main: joining thread...\n");
	pthread_join(tid, NULL);

	/* Done */
	printf("Main: exiting...\n");
	return (0);
}

---------------------------------------------------------------------------

>Fix:

	Looks like the PTHREAD_AT_CANCEL_POINT flag needs to be set for the
	current thread in the libc_r version of poll(2).

	NOTE: there may be other system calls with this same problem.
	Perhaps a quick audit should be done.


>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200205020130.g421UfB04028>