what is going on here ???
ab at unido.UUCP
ab at unido.UUCP
Thu Jun 27 04:29:00 AEST 1985
> If you are running 4.2, look at the following short program and
> guess what it will do. Then compile and run it and find out
> what it really does.
>
> Try to explain its behavior!! (- Is it a bug in 4.2 ??? :-) )
Here is the solution to the previously posted 'puzzle':
It is a nice method to terminate all running shells which share
the controlling terminal. -- And it is an example of unexpected
side-effects, caused by a relatively small and hidden bug.
The bug was produced by a typo in the statement which opens /dev/kmem.
Notice the wrong positions of the parentheses:
> if((kmem = open ("/dev/kmem", 0) < 0)) {
kmem stays 0 and the lseek on kmem is actually done on stdin !!!
The lseek takes the read/write-pointer of the terminal-channel to
an unaccessible position and all following reads or writes of any
process from/to the terminal will fail. This will cause all shells
to terminate! (See also the source below.)
Andreas Bormann ab at unido.UUCP
University of Dortmund N 51 29' 05" E 07 24' 42"
West Germany
--- CUT HERE ---------- CUT HERE ---------- CUT HERE ---------- CUT HERE ----
#include <nlist.h>
#define NAMELIST "/vmunix"
struct nlist avenrun[] = {
{ "_avenrun" },
{ "" }
};
main()
{
register int kmem;
double avg[3];
if((kmem = open ("/dev/kmem", 0) < 0)) { /* HERE's THE BUG !!! */
/*
* If the open-call succeeds, it will return a positive filedescriptor
* and kmem will be 0 because the positive descriptor isn't less than 0.
*
* This is the corrected statement:
*
* if((kmem = open ("/dev/kmem", 0)) < 0) {
*/
printf("Cannot open kmem\n");
exit(1);
}
nlist(NAMELIST, avenrun);
if(avenrun[0].n_type == 0) {
printf("Cannot find avenrun\n");
exit(1);
}
/*
* Remember: kmem == 0 !!
* avenrun[0].n_value is something like -2147230472,
* so the lseek will seek the read/write-pointer ON THE STDIN to
* an unaccessible position.
*/
lseek(kmem, (long) avenrun[0].n_value, 0);
/*
* All successive reads by all processes which share the terminal
* will now return an error (-1) and the parent shells will terminate!!!
*/
read(kmem, (char *) avg, 3 * sizeof (double));
printf("Load average: %f %f %f\n", avg[0], avg[1], avg[2]);
exit(0);
}
More information about the Comp.unix
mailing list