Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!ames!ubvax!ardent!rap From: rap@ardent.UUCP (Rob Peck) Newsgroups: comp.sys.amiga.tech Subject: Re: Manx help Keywords: Manx Aztec DOS Locks Message-ID: <679@ardent.UUCP> Date: 28 Oct 88 19:28:56 GMT References: <5918@killer.DALLAS.TX.US> Organization: Dana Computer, Inc., Sunnyvale, CA Lines: 141 In article <5918@killer.DALLAS.TX.US>, jdp@killer.DALLAS.TX.US (Jim Pritchett) writes: > out? Basically the problem is that although the test program below runs fine, > the system becomes severely unstable and crashes within a couple of commands > after the program terminates. I'm sure that there is a problem with my > (mis)understanding of locks, but I don't know what it is. Here is the source > code to my program (Aztec C v3.6a, SDB): > > lockram = Lock("ram:t", ACCESS_READ); > lockcd = CurrentDir(lockram); > (material deleted for brevity) > UnLock(lockram); > lockram = CurrentDir(lockcd); > (material deleted for brevity) > > UnLock(lockcd); > UnLock(lockram); > I experimented and found out (and documented it in the Programmers' Guide) that you should NOT unlock a lock that you get from CurrentDir. ======================================================================= AmigaLINE: Care and Feeding of AmigaDOS 'locks'. Rob Peck ONLY unlock locks that you get from Lock() or DupLock(). It seems that when using CurrentDir(), the system simply hands you a pointer to a lock that it already was using for something else... I believe it is the lock associated with the current CLI's current directory. If you unlock this, you return the resource to the system which can then reuse that memory For any other purpose. The instability you see I believe is that the CLI from which you started the program still has a pointer to that memory and when it tries to use it for something, GURU (maybe). The simplest experiment you can do to confirm this is the following (done from memory cause my book is not here at this moment): #include "exec/types.h" #include "functions.h" #include "libraries/dos.h" #include "libraries/dosextens.h" main() { /* INCORRECT METHOD #1 */ struct FileLock *testlock, *aarrgghh; testlock = Lock("RAM:",ACCESS_READ); aarrgghh = CurrentDir(testlock); UnLock(aarrgghh); UnLock(testlock); } #include "exec/types.h" #include "functions.h" #include "libraries/dos.h" #include "libraries/dosextens.h" main() { /* INCORRECT METHOD #2 */ struct FileLock *testlock, *aarrgghh; testlock = Lock("RAM:",ACCESS_READ); aarrgghh = CurrentDir(testlock); UnLock(aarrgghh); /* see, did not even unlock testlock */ } On exiting either version, try the command 'DIR', or 'LIST'. You may be surprised at the results. This code WILL destabilize a system because CurrentDir returns a pointer to the lock on the PREVIOUS directory, but puts the program into the directory associated with the new lock you have obtained. The purpose for CurrentDir (and ParentDir) for that matter, returning the PREVIOUS lock is so you can freely move around in the directory tree. When ParentDir returns a NULL BPTR, it means you are at the root of that filing system and cannot parent-up any further, but you do get the pointer to the lock on the previous directory so that you can move back down to wherever you wish to go. Likewise with CurrentDir, you get the previous one so that, for example, your program can go out of the current directory to retrieve music or other files to which you have been given a lock (for example in a Workbench argument), then come back to your own current directory to retrieve other files you may need - that directory from whence you started: newlock = Lock("new.directory", ACCESS_READ); oldlock = CurrentDir(newlock); /* do stuff in new directory */ ignoredlock = CurrentDir(oldlock); /* returns you to where you started. */ Notice that I called this one "ignored lock" because once I finished with the new directory, I was given a pointer to the lock that I had handed to CurrentDir earlier. So I can safely ignore it if I simply remember to UnLock(newlock) later, because in this case, ignoredlock == newlock which simply means that if you UnLock something given to you by CurrentDir AND unlock something given to you by Lock, you are unlocking the same thing TWICE, ... same effect as freeing the same memory twice and the system fails eventually. So the RULE is: NEVER UnLock any lock given to you by either CurrentDir() or ParentDir(). ONLY UnLock a lock provided to you by Lock() or DupLock(). Those BELONG to you. The others just might have been created by the system and it will not realize you have killed them -- when it tries to reuse them, the GURU may visit. #include "exec/types.h" #include "functions.h" #include "libraries/dos.h" #include "libraries/dosextens.h" main() { /* CORRECT METHOD */ struct FileLock *testlock, *aarrgghh; testlock = Lock("RAM:",ACCESS_READ); aarrgghh = CurrentDir(testlock); /* aarrgghh is a pointer to the lock on the * directory that the CLI started from... * it may still need that lock sometime later. * If we free it by UnLock, we mess things up. */ UnLock(testlock); /* Did nothing more than move current CLI's * current directory to ram: */ }