kern/118287: [PATCH] tty write is not always atomic for small lines

Charles Hardin chardin at 2wire.com
Tue Nov 27 10:00:05 PST 2007


>Number:         118287
>Category:       kern
>Synopsis:       [PATCH] tty write is not always atomic for small lines
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 27 18:00:02 UTC 2007
>Closed-Date:
>Last-Modified:
>Originator:     Charles Hardin
>Release:        FreedBSD-CURRENT
>Organization:
2Wire Inc.
>Environment:
>Description:
During test automation there has been some unexpected failures because output from different processes has been interspersed.
>How-To-Repeat:
Using the following test code

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int
main(int argc, char **argv)
{
    char buf[512];
    int res, len;

    if (daemon(0, 1) != 0) {
        return 1;
    }

    len = snprintf(buf, sizeof(buf), "<This is writerd pid %d.>\n", getpid());
    if (len >= sizeof(buf)) {
        return 2;
    }
    while (1) {
        res = write(1, buf, len);
        if (res != len) {
            return 3;
        }
    }
}

when running a couple copies of this, it sometimes prints out this:

    <This is writerd pid 28.><This is writerd pid 30.>
    <This is writerd pid 30.>
    ...more lines like that...
    <This is writerd pid 30.>

    <This is writerd pid 28.>

In other words, several writes from pid 30 happen in the middle of a write from
pid 28

>Fix:
So, the attached diff modifies the behavior of ttwrite to try and dump at least OBUFSIZ at a time in the clist so that lines shorter than OBUFSIZ should never be intermingled... This solves 99% of the cases and is easy enough for us to fix the user code to keep it solved...

Patch attached with submission follows:

Index: tty.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/tty.c,v
retrieving revision 1.273
diff -u -r1.273 tty.c
--- tty.c	20 Jul 2007 09:41:54 -0000	1.273
+++ tty.c	27 Nov 2007 17:49:13 -0000
@@ -2046,13 +2046,16 @@
 	int i, hiwat, cnt, error, s;
 	char obuf[OBUFSIZ];
 
-	hiwat = tp->t_ohiwat;
 	cnt = uio->uio_resid;
 	error = 0;
 	cc = 0;
 	td = curthread;
 	p = td->td_proc;
 loop:
+	/* set a slightly different hi water mark to transfer at least
+	 * OBUFSIZ characters from the user write at a time.
+	 */
+	hiwat = imax(tp->t_ohiwat - OBUFSIZ, tp->t_olowat);
 	s = spltty();
 	if (ISSET(tp->t_state, TS_ZOMBIE)) {
 		splx(s);
@@ -2165,7 +2168,7 @@
 					cp++;
 					cc--;
 					if (ISSET(tp->t_lflag, FLUSHO) ||
-					    tp->t_outq.c_cc > hiwat)
+					    tp->t_outq.c_cc > tp->t_ohiwat)
 						goto ovhiwat;
 					continue;
 				}
@@ -2198,7 +2201,7 @@
 				goto loop;
 			}
 			if (ISSET(tp->t_lflag, FLUSHO) ||
-			    tp->t_outq.c_cc > hiwat)
+			    tp->t_outq.c_cc > tp->t_ohiwat)
 				break;
 		}
 		ttstart(tp);


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


More information about the freebsd-bugs mailing list