carl@umd5 (Carl Symborski) (01/15/87)
Here's another VT100 bug and associated fix to Dave Wecker's famous VT100 terminal program. The problem is that VT100 seemed to cause the workbench to hang/crash after exit from VT100. Steve Walton mentioned in a recent posting that this happened only when VT100 was run from the workbench (i.e. invoked via double click on icon). After exit, clicking on workbench icons would not do anything etc... I have also been having this problem, sometimes accompanied by software task held messages, guru's etc. Anyway, my environment is VT100 V2.3, Lattice V3.03, Release 1.1 of OS. It turns out that the problem is with the Change Dir menu command. Using this feature will cause the above problem ONLY when running from workbench. Quick fix: Don't use Change Dir... or use VT100 only from CLI. The trouble is in the set_dir routine in expand.c, which does something like: if (lock = (struct FileLock *)CurrentDir(lock)) UnLock(lock); Where "lock" is a lock on the directory to switch to. CurrentDir returns the lock on the "old" current dir, which is then unlocked. This works in all cases EXCEPT the first time through! When a tool (like VT100) is started from the workbench, Workbench will (among other things) create an argument for the workbench startup message containing the name of the tool in the wa_Name field and a lock of the directory where the tool is in the wa_Lock field. This is linked into the startup message and sent to the tool at startup. The stardard Lattice startup code (Lstartup.obj) plucks the lock out of this message and does a CurrentDir on it. So... the first time through VT100's set_dir processing, the lock returned from CurrentDir will be that same lock created by the Workbench. You can bet that Workbench wants to UnLock this lock as part of its cleanup processing after VT100 exits and the startup message is replied back. So if VT100 unlocks the lock, and later Workbench unlocks the same lock... CRASH! This is the heart of the problem. All of this workbench stuff dosn't happen when RUNning under the CLI. Thats why this is not a problem under the CLI. There are also a few more minor bugs in the set_dir routine which may or maynot have contributed to the original problem. Lock was being called without specifying the "accessMode" parameter (it was missing). Examine was being called with with a stack based "FileInfoBlock" structure. The AmigaDOS Developers Manual says that the FileInfoBlock must be longword aligned. I don't think this is guaranteed with stack variables. Finally, the lock obtained on the LAST directory set by set_dir is never unlocked by anyone. This contributes to gradual memory loss. What follows are edits to three VT100 files: VT100.h, VT100.c, and EXPAND.c Crank up your favoriate editor, locate the modified areas, insert new lines marked by the arrows. Recompile VT100.c and EXPAND.c, alink and your done. ------ CHANGES TO VT100.H ------ VT100.h changed in two places. Search for "MyDir" and insert new declaration of "MyDirLock"... int multi = FALSE, server; long bytes_xferred; char MyDir[60]; struct FileLock *MyDirLock = NULL; <----------- NEW struct IntuitionBase *IntuitionBase; Search for "MyDir" again and insert new external declaration of "MyDirLock"... extern char bufr[BufSize]; extern int fd, timeout, ttime; extern long bytes_xferred; extern char MyDir[60]; extern struct FileLock *MyDirLock; <------------ NEW ------ CHANGES TO VT100.C ------ One addition to VT100.C. Search for "cleanup" function. Add UnLock to case 0 processing... cleanup(reason, fault) char *reason; int fault; { switch(fault) { case 0: /* quitting close everything */ ClearMenuStrip( mywindow ); CloseDevice(&Audio_Request); if (MyDirLock != NULL) UnLock(MyDirLock); <------- NEW ------ CHANGES TO EXPAND.C ------ Replace "set_dir" routine with the set_dir which follows... set_dir(new) char *new; { register char *s; int i; struct FileLock *lock; char temp[60]; struct FileInfoBlock *fib; if (*new != '\000') { strcpy(temp, MyDir); s = new; if (*s == '/') { s++; for (i=strlen(MyDir); MyDir[i] != '/' && MyDir[i] != ':'; i--); MyDir[i+1] = '\0'; strcat(MyDir, s); } else if (exists(s, ':') == 0) { if (MyDir[strlen(MyDir)-1] != ':') strcat(MyDir, "/"); strcat(MyDir, s); } else strcpy(MyDir, s); if ((lock = (struct FileLock *)Lock(MyDir, ACCESS_READ)) == 0) { emits("Directory not found\n"); strcpy(MyDir, temp); } else { fib = (struct FileInfoBlock *)AllocMem( (long)sizeof(struct FileInfoBlock), MEMF_PUBLIC); if (fib) { if (Examine(lock, fib)) { if (fib->fib_DirEntryType > 0) { CurrentDir(lock); if (MyDirLock != NULL) UnLock(MyDirLock); MyDirLock = lock; if (MyDir[strlen(MyDir)-1] == '/') MyDir[strlen(MyDir)-1] = '\0'; } else { emits("Not a Directory\n"); strcpy(MyDir,temp); } } FreeMem(fib, (long)sizeof(struct FileInfoBlock)); } else { emits("Can't change Directory... no free memory!\n"); strcpy(MyDir,temp); } } } } -------- END OF FIXES -------- I have to say CHEERS to those people who post sources along with their PD offerings!! This way we can fix those bugs we want to fix, when we want to fix them, AND learn something in the process. I think of this often whenever I read; "... what follows is the UUENCODED binary of my program X. Download this and...". Sufficient provocation for the "j" key, or perhaps the "^c". A good way to keep up with the mail, ay? Carl Symborski