Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: notesnews 0.1 (unido 12/05/84); site unido.UUCP Path: utzoo!watmath!clyde!cbosgd!cbdkc1!desoto!packard!hoxna!houxm!mtuxo!mtunh!mtung!mtunf!ariel!vax135!timeinc!phri!pesnta!amd!vecpyr!lll-crg!gymble!umcp-cs!seismo!mcvax!unido!ab From: ab@unido.UUCP Newsgroups: net.unix Subject: Re: what is going on here ??? Message-ID:Date: Wed, 26-Jun-85 14:29:00 EDT Article-I.D.: unido.nf11400003 Posted: Wed Jun 26 14:29:00 1985 Date-Received: Tue, 2-Jul-85 05:47:09 EDT References: Sender: notes@unido.UUCP Lines: 76 Nf-ID: #R:unido:11400002:unido:11400003:000:2266 Nf-From: unido!ab Jun 26 14:29:00 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@unido.UUCP University of Dortmund N 51 29' 05" E 07 24' 42" West Germany --- CUT HERE ---------- CUT HERE ---------- CUT HERE ---------- CUT HERE ---- #include #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); }