From nobody@FreeBSD.ORG Wed Nov  3 07:48:47 1999
Return-Path: <nobody@FreeBSD.ORG>
Received: by hub.freebsd.org (Postfix, from userid 32767)
	id E1DA914DBD; Wed,  3 Nov 1999 07:48:46 -0800 (PST)
Message-Id: <19991103154846.E1DA914DBD@hub.freebsd.org>
Date: Wed,  3 Nov 1999 07:48:46 -0800 (PST)
From: xfb52@dial.pipex.com
Sender: nobody@FreeBSD.ORG
To: freebsd-gnats-submit@freebsd.org
Subject: setjmp/longjmp in threaded app cause subsequent read to run forever
X-Send-Pr-Version: www-1.0

>Number:         14685
>Category:       kern
>Synopsis:       setjmp/longjmp in threaded app cause subsequent read to run forever
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov  3 07:50:00 PST 1999
>Closed-Date:    Tue Jan 18 23:30:05 PST 2000
>Last-Modified:  Tue Jan 18 23:30:41 PST 2000
>Originator:     Alex Zbyslaw
>Release:        3.2
>Organization:
>Environment:
FreeBSD stimpy 3.2-RELEASE FreeBSD 3.2-RELEASE #3: Tue Oct 26 19:23:46 BST 1999     alex@stimpy:/usr/src/sys/compile/SHERPA  i386

>Description:
If a program linked against libc_r is looping on a read, the read is
interrupted, and the signal handler uses a longjmp to jump back
to just before the read, the read call will go into an infinite loop.

As far as I have trace it, everything goes wrong somewhere in 
_thread_kern_poll

This is a big problem (for me) as this is exactly how python interacts
libreadline.


>How-To-Repeat:
Compile the following program
e.g. gcc -pthread -o readtest readtest.c

Type a few keys to see that it is working OK, and then press ^C.

I used ktrace/kdump -l to watch what happened when keys were pressed
and when ^C was pressed.  After a keypress the process ends up doing a
gettimeofday() and then a poll() but after a ^C it does the
gettimeofday() but never reaches a poll.  top shows it in a RUN state
chewing up mucho CPU.

#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <termios.h>
#include <signal.h>
#include <setjmp.h>

extern int errno;
static jmp_buf jbuf;

void
onintr()
{
  printf("\nCAUGHT INT\n");
  longjmp(jbuf, 1);
}

int
main (argc, argv)
     int argc;
     char **argv;
{
  unsigned char c;
  int result;
  int flags;
  struct termios tio;
  struct sigaction act;

  act.sa_handler = onintr;
  act.sa_mask = SIGINT;
  act.sa_flags = 0;

  sigaction(SIGINT, &act, NULL);


  
  tcgetattr(fileno(stdin), &tio);
  tio.c_lflag &= ~(ICANON);

  tcsetattr(fileno(stdin), TCSANOW, &tio);
  

  while (1) {
    if (setjmp(jbuf)) {
      printf("\nIN SETJMP\n");
    }


    result = read(fileno(stdin), &c, sizeof(unsigned char));
    
    if (result == 0 || c == 4) {
      printf ("\nEOF\n");
      exit (0);
    }

    if (result == sizeof(unsigned char)) {
      printf ("\nREAD: %c\n", c);
      continue;
    }

    printf ("\nERROR: %s\n", strerror(errno));
  }
}


>Fix:


>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->closed 
State-Changed-By: jasone 
State-Changed-When: Tue Jan 18 23:30:05 PST 2000 
State-Changed-Why:  
Fixed in -current. 
>Unformatted:
