Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 4 Aug 2002 14:34:29 -0700 (PDT)
From:      Antti Louko <alo@iki.fi>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   misc/41331: Pthread library open sets O_NONBLOCK flag and causes unnecessary EAGAIN errors especially with /dev/stdout.
Message-ID:  <200208042134.g74LYTM6074371@www.freebsd.org>

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

>Number:         41331
>Category:       misc
>Synopsis:       Pthread library open sets O_NONBLOCK flag and causes unnecessary EAGAIN errors especially with /dev/stdout.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Aug 04 14:40:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Antti Louko
>Release:        4.5
>Organization:
>Environment:
FreeBSD xxx.louko.com 4.5-RELEASE FreeBSD 4.5-RELEASE #1: Tue Mar  5 23:48:33 EET 2002     root@xxx.louko.com:/xxx/src/sys/compile/ALO  i386   
>Description:
When using threads, the threads library
(/usr/src/lib/libc_r/uthread/uthread_fd.c) sets O_NONBLOCK for each
new opened file and fails to emulate the blocking write(2) correctly.
This affects eg. when a program opens /dev/stdout for writing and thje
reader process is slower than the writer.  The writer gets EAGAIN
error which shouldn't happen when the open call didn't specify
O_NONBLOCK flag.

>How-To-Repeat:
Run the following program (compiled with gcc -pthread -o writer
writer.c) and feed its output to the shell script:

./writer | sh reader.sh

reader.sh:
----------------------------------------
#! /bin/sh
while :
do
  dd of=/dev/null bs=1k count=1
  sleep 1
done
----------------------------------------

writer.c
----------------------------------------
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>

main(int argc, char **argv)

{
  char  buf[1024];
  int   fd;
  int   i;
  int   total = 0;

  fd = open("/dev/stdout",O_WRONLY|O_CREAT|O_TRUNC,0666);
  if (fd == -1) {
    int e;
    e = errno;
    fprintf(stderr,"open, errno: %d\n",e);
    exit(1);
  }
  for(i = 0; i < sizeof(buf); i++)
    buf[i] = 'a' + (i % 26);
  for(;;) {
    int n;
    n = write(fd,buf,sizeof(buf));
    if (n > 0)
      total += n;
    if (n != sizeof(buf)) {
      int       e;
      e = errno;
      fprintf(stderr,"write, errno: %d\n",e);
      fprintf(stderr,"Total bytes written %d\n",total);
      exit(1);
    }
  }
}
----------------------------------------
Run the following program (compiled with gcc -pthread -o writer
writer.c) and feed its output to the shell script:

./writer | sh reader.sh

reader.sh:
----------------------------------------
#! /bin/sh
while :
do
  dd of=/dev/null bs=1k count=1
  sleep 1
done
----------------------------------------

writer.c
----------------------------------------
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>

main(int argc, char **argv)

{
  char  buf[1024];
  int   fd;
  int   i;
  int   total = 0;

  fd = open("/dev/stdout",O_WRONLY|O_CREAT|O_TRUNC,0666);
  if (fd == -1) {
    int e;
    e = errno;
    fprintf(stderr,"open, errno: %d\n",e);
    exit(1);
  }
  for(i = 0; i < sizeof(buf); i++)
    buf[i] = 'a' + (i % 26);
  for(;;) {
    int n;
    n = write(fd,buf,sizeof(buf));
    if (n > 0)
      total += n;
    if (n != sizeof(buf)) {
      int       e;
      e = errno;
      fprintf(stderr,"write, errno: %d\n",e);
      fprintf(stderr,"Total bytes written %d\n",total);
      exit(1);
    }
  }
}
----------------------------------------
Run the following program (compiled with gcc -pthread -o writer
writer.c) and feed its output to the shell script:

./writer | sh reader.sh

reader.sh:
----------------------------------------
#! /bin/sh
while :
do
  dd of=/dev/null bs=1k count=1
  sleep 1
done
----------------------------------------

writer.c
----------------------------------------
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>

main(int argc, char **argv)

{
  char  buf[1024];
  int   fd;
  int   i;
  int   total = 0;

  fd = open("/dev/stdout",O_WRONLY|O_CREAT|O_TRUNC,0666);
  if (fd == -1) {
    int e;
    e = errno;
    fprintf(stderr,"open, errno: %d\n",e);
    exit(1);
  }
  for(i = 0; i < sizeof(buf); i++)
    buf[i] = 'a' + (i % 26);
  for(;;) {
    int n;
    n = write(fd,buf,sizeof(buf));
    if (n > 0)
      total += n;
    if (n != sizeof(buf)) {
      int       e;
      e = errno;
      fprintf(stderr,"write, errno: %d\n",e);
      fprintf(stderr,"Total bytes written %d\n",total);
      exit(1);
    }
  }
}
----------------------------------------

>Fix:
      
>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?200208042134.g74LYTM6074371>