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>
