msm@nucleus.mi.org (Michael S. Mattone) (04/07/90)
I've noticed a few bugs in MINIX 1.5.5. I'm posting this in case any
of these haven't been noticed before. Maybe they will make it into
official 1.5.6 changes to be posted in April.
1. Pipe limit 7K. The following fails if 'fd' is a pipe:
write(fd, buf, 8000);
This bug (feature?) has been annoying me since 1.2. Anyone else?
I posted my modifications to make this problem go away 2 1/2 times
before. Should I try for 3 1/2? Or is this something POSIX requires?
2. Named Pipes. I was playing with named pipes and ran into
a few problems. Since a named pipe doesn't disappear like a normal
pipe until it is unlinked, the trick being used to allow de(1) to
recover deleted files causes problems. The message:
FS freeing unused block of inode, bit = #
^^ - typo? should this be "or"
is displayed when rm'ing a named pipe, and messes up the filesystem.
This appears easy to fix in fs/link.c by calling wipe_inode()
in truncate() if the inode is associated with a pipe.
Cdiff included below.
3. Incompatible mknod(). The V7 UNIX mknod(2) takes three arguments,
mknod(name, mode, addr) but MINIX requires a fourth arg to
specify the size of a device. For portability and compatibility
with UNIX, could the MINIX mknod() be renamed to something like
mknodx() and a UNIX compatible mknod() that calls mknodx()
with a 0 for the size argument? MINIX programs that need to would
use mknodx(), ported programs wouldn't need to know mknod() was
different.
4. Shell read built-in. The shell doesn't handle:
read arg1 arg2 ... argN
properly if fewer than N words are entered by the user. As delivered
the shell forces the user to type a return for each of the left over
arguments that there aren't words for.
Another cdiff for commands/sh/sh3.c is included.
--------------------------------cut here--------------------------------
echo x - link.cdif
sed '/^X/s///' > link.cdif << '/'
X*** link.c.old Fri Apr 6 16:47:47 1990
X--- link.c Fri Apr 6 16:47:47 1990
X***************
X*** 310,316 ****
X register zone_nr z, *iz;
X off_t position;
X zone_type zone_size;
X! int scale, file_type;
X struct buf *bp;
X dev_t dev;
X
X--- 310,316 ----
X register zone_nr z, *iz;
X off_t position;
X zone_type zone_size;
X! int scale, file_type, waspipe;
X struct buf *bp;
X dev_t dev;
X
X***************
X*** 319,325 ****
X dev = rip->i_dev; /* device on which inode resides */
X scale = scale_factor(rip);
X zone_size = (zone_type) BLOCK_SIZE << scale;
X! if (rip->i_pipe == I_PIPE) rip->i_size = PIPE_SIZE; /* pipes can shrink */
X
X /* Step through the file a zone at a time, finding and freeing the zones. */
X for (position = 0; position < rip->i_size; position += zone_size) {
X--- 319,326 ----
X dev = rip->i_dev; /* device on which inode resides */
X scale = scale_factor(rip);
X zone_size = (zone_type) BLOCK_SIZE << scale;
X! if (waspipe = (rip->i_pipe == I_PIPE))
X! rip->i_size = PIPE_SIZE; /* pipes can shrink */
X
X /* Step through the file a zone at a time, finding and freeing the zones. */
X for (position = 0; position < rip->i_size; position += zone_size) {
X***************
X*** 344,348 ****
X }
X
X /* Leave zone numbers for de(1) to recover file after an unlink(2). */
X! rip->i_dirt = DIRTY;
X }
X--- 345,351 ----
X }
X
X /* Leave zone numbers for de(1) to recover file after an unlink(2). */
X! if (waspipe)
X! wipe_inode(rip); /* clear out inode for pipes */
X! rip->i_dirt = DIRTY;
X }
/
echo x - sh3.cdif
sed '/^X/s///' > sh3.cdif << '/'
X*** sh3.c.old Tue Feb 20 04:26:37 1990
X--- sh3.c Tue Feb 20 12:29:01 1990
X***************
X*** 776,790 ****
X {
X register char *cp, **wp;
X register nb;
X
X if (t->words[1] == NULL) {
X err("Usage: read name ...");
X return(1);
X }
X for (wp = t->words+1; *wp; wp++) {
X! for (cp = e.linep; cp < elinep-1; cp++)
X! if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
X! *cp == '\n' ||
X wp[1] && any(*cp, ifs->value))
X break;
X *cp = 0;
X--- 776,791 ----
X {
X register char *cp, **wp;
X register nb;
X+ register int nl = 0;
X
X if (t->words[1] == NULL) {
X err("Usage: read name ...");
X return(1);
X }
X for (wp = t->words+1; *wp; wp++) {
X! for (cp = e.linep; !nl && cp < elinep-1; cp++)
X! if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
X! (nl = (*cp == '\n')) ||
X wp[1] && any(*cp, ifs->value))
X break;
X *cp = 0;
/
exit 0archer%segin4.segin.fr@prime.com (Vincent Archer) (04/09/90)
Michael S. Mattone <msm@NUCLEUS.MI.ORG> says:
MSM>1. Pipe limit 7K. The following fails if 'fd' is a pipe:
MSM> write(fd, buf, 8000);
MSM> This bug (feature?) has been annoying me since 1.2. Anyone else?
MSM> I posted my modifications to make this problem go away 2 1/2 times
MSM> before. Should I try for 3 1/2? Or is this something POSIX requires?
Better yet, it fails with a specific error code saying that it's too big (8000
that is). That's because Unix requires writes to be atomic. Otherwise, you
could find (assuming two processes writing onto the same pipe) the following
situation:
P1 says: write(8000)
the pipe accepts 7K, and P1 waits
P1 gets: signal -9
and is killed. FS notices this and purges the remaining 1K
P2 says: read(8000)
and gets the 7K, but never the 1K (missing)
In that situation, you get a partial block of data. If you're using your pipe
as a formatted packet stream, you wind up with a non-terminated packet. This
can get annoying sometimes, and Unix therefore tries to forbid a write to be
done in two (or more) chunks. Do not correct this behaviour, it's standard
practice on Unix.
Vincent Archer
Email: archer%segin4.segin.fr@prime.com (Yes, indirect address required!)