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>