Path: utzoo!mnetor!uunet!husc6!bbn!rochester!udel!burdvax!bpa!cbmvax!rutgers!aramis.rutgers.edu!athos.rutgers.edu!hedrick From: hedrick@athos.rutgers.edu (Charles Hedrick) Newsgroups: comp.unix.microport Subject: odd behavior in read Message-ID: Date: 12 Mar 88 21:47:26 GMT Organization: Rutgers Univ., New Brunswick, N.J. Lines: 83 Cc: uport!techs I've been playing with jove (a dialect of Emacs) under SV/AT. It is essentially unusable. Every 30 seconds, it hangs for about 5 seconds with the disk making noises like it is being swapped. During this time, if you type anything it is lost. I believe I now know most of what is going on, and it is rather alarming (SIGALRM'ing, to be precise). So here goes: Jove likes to display the time on the mode line. In order to keep this up to date, it uses alarm (2). The code is classical: There is a short subroutine that gets the time and updates the mode line. It ends by doing alarm(30) to set the next alarm, and signal(SIGALRM,) with itself as the second argument, to set things so that it gets called on the alarm. The code for reading a character then has to be able to deal with the possibility that read will return -1 with EINTR, because of the lousy System V interrupt semantics. Anyway, this arrangement manages to trigger what looks like one serious performance deficiency and one outright bug in the kernel. (If it isn't a bug, then the people who wrote the SVID should be shot.) First, most of the time when the alarm happens, the disk drive makes noises like the process is being swapped out and in. This happens even when I have been typing to it, and there's no other program running, so I know it is swapped in. During the time that these swapping noises are going on, any characters I type are lost. I put some hacks into the character read routine. I clear the read buffer to nulls before doing the read. If read returns < 0, I do a strlen on the buffer to see whether there's anything there. It turns out that read does in fact return the characters I have typed, but it sets EINTR and returns something < 0, so the code quite correctly believes there is nothing there. OK, here are the bugs I claim: 1) the program should not swap everytime an alarm goes off. I assume it is doing this because of the usual problems with memory management. (I've seen this before with sbrk, as reported in this group.) While I'm sympathetic with the problems of memory allocation using the blasted 286 chip, I don't see how we can live with a system that swaps your program everytime it takes a signal. 2) If read has returned data, it should return a count of the data, not an error. This is obviously a matter of definition, and it's always possible that SV/AT is following the SVID (I don't happen to have it handy). But clearly you want your code to look like do nchar = read(0, buffer, sizeof buffer); while (nchar < 0 && errno == EINTR); (Well, actually you want the read to continue automatically after the signal, so you just need the read, but that's BSD, and it would be too much to expect SV to work like BSD. Maybe in SV release 4...) The current semantics require you to do do { bzero(buffer, sizeof buffer); nchar = read(0, buffer, sizeof buffer); if (nchar < 0) nchar = strlen(buffer); } while (nchar < 0 && errno == EINTR); which is completely absurd, not to mention that it doesn't let you read nulls all the time, and null happens to be an important command in Emacs. 3) Even with the completely absurd code above, if I type more characters than the size of the buffer, the extra ones appear to be lost. I am mentioning all of this to the group, rather than just SPR'ing it to Microport, because I'm hoping someone else will know enough about System V to verify my understanding that this is a bug. I can't help wondering whether something like this is happening in UUCP, and may be at least part of the explanation of the continual problems people have getting reliable UUCP connections. PS: for those of you that like jove, it's possible to use it, but you have to turn off all the timers, so it doesn't use alarm. When I get a version I like, I'll post the diffs. I will probably use a variant of the horrible hack shown above, so that it is safe to use the timers.