🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.bugs.4bsd
Article #1391

Shared file descriptors

#1391
From: Gil Shwed
Date: Tue, 30 May 1989 14:36
83 lines
2813 bytes
Description:

	Child/Father processes sharing of file descriptors does not
work correctly. When two or more processes are reading simultaneously from
using the same file descriptor (as resulted from fork())
the file offset does not increment properly.
Resulting in reading the same blocks by number of processes,
and skipping others.

This bug exist on *ALL* the Berkeley derived system I've checked,
which includes: VAXen, ALL Suns, Sequent DYNIX, Gould, CCI TAHOE, and others.

Repeat-By:
	Compile the following program:
	main() {
		char buf[8192];
		int n;

		fork();
		while((n = read(0, buf, 8192)) > 0)
			write(1, buf, n);
		exit(0);
	}
	Then, run:

		a.out < /vmunix > out

	Now, run:
		cmp /vmunix out

	They should be the same, but...

Explanation:

	The routine rwuio() in the file sys/sys_generic.c has the following
	structure:

	count = uio->uio_resid;		/* Take count to read/write */
	uio->uio_offset = fp->f_offset;	/* (a) Offset in file */
	.
	.
					/* (b) perform actual i/o */
	u.u_error = (*fp->f_ops->fo_rw)(fp, rw, uio);
	u.u_r.r_val1 = count - uio->uio_resid;
	fp->f_offset += u.u_r.r_val1;	/* (c) Update file offset */


	When the first process enters this routine, it tries to read
	from position 0 (a), it enters file-type specific function (ino_rw),
	and blocks until the block is brought from disk.
	Then, the second processes gets the cpu and perform the same
	operation: It enters read()->rwuio(), takes the file offset (a),
	which is *NOT* modified to reflect the first read.
	This results in reading the same block twice!
	Furthermore, when the two processes gets their (same) block,
	they update the file offset (c) *TWICE*.
	So... the next read will skip a block.

	Or in the example, the output file will contain the following
	data blocks (numbered as the block number from the original file):
		0, 0, 2, 2, ...., n, n
	Instead of:
		0, 1, 2, 3, ...., n-1, n


Fix:
	The problem should be fixed by locking the inode before
	taking the offset (This is the way SystemV does it).
	This is sort of architectural problem, since rwuio()
	does not suppose to know the file type and/or recognize
	ILOCK().
	So, I leave the right to fix this bug the people who
	wrote it that way the first place...


-- Have Fun!
-- Gil Shwed

Or one of the following:
gil%taux01@nsc.com
gil@hujifh.bitnet
gil@humus.huji.ac.il
gil@batata.bitnet
Technical Details
Message-ID: <1770@taux01.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!apple!voder!nsc!taux01!gil

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!apple!voder!nsc!taux01!gil
From: gil@taux01.UUCP ( Gil Shwed)
Newsgroups: comp.bugs.4bsd,comp.unix.wizards
Subject: Shared file descriptors
Message-ID: <1770@taux01.UUCP>
Date: 30 May 89 14:36:49 GMT
Reply-To: gil%taux01@nsc.COM (Gil Shwed)
Organization: National Semiconductor (IC) Ltd, Israel
Lines: 83