>Date: Tue, 21 Mar 2000 17:25:18 +0100
>I have the same problem with database application written in Clipper
>(d-base clone). When using local data or samba volume, locking doesn't
>work. But when I use NetWare (MARS emulator) on server side and netx
>(NetWare network shell) within dosemu, locking works fine. I tried it on
Because it is not serviced via DosEmu FS redirector.
>small network (five clients) without problems. There is one (important)
>drawback - when application lock file, CPU usage riases to 100% and
>stays there until app unlock the file.
Because the application has a "bug" - the correct action when
a file or record is locked is delay, then retry, the application
either delays by a loop (using CPU) or retries w/o delay. Correct
code should invoke INT 28h inside the delay loop and wait e.g.
time at 40:6c to change (to limit I/O to 18.2 times/second).
>Question: Why locking don't work in plain dosemu and with netx does?
>
>Note: I tried MS-DOS 6.22, MS-DOS 5.0, MS-DOS 7.0, DR-DOS 7.03 and
>dosemu 0.66,0.98.x,0.99.x,1.0.0, with the same results.
Yes, yes, there is a bug in DosEmu. I just wrote a fix.
For version 0.98.8 (not the new 1.00), unfortunately.
Here is the fix (diffs of the source), and some notes from my work:
--- dosemu-0.98.8/src/dosext/mfs/mfs.c- Sun Jul 4 22:38:36 1999
+++ dosemu-0.98.8/src/dosext/mfs/mfs.c Tue Mar 21 15:59:04 2000
@@ -3737,7 +3737,17 @@
ret = fcntl (fd,F_SETLK,&larg);
Debug0((dbg_fd, "lock fd=%x rc=%x type=%x whence=%x start=%lx,
len=%lx\n",
fd, ret, larg.l_type, larg.l_whence, larg.l_start,larg.l_len));
+#if 0
return ret != -1 ? TRUE : FALSE;
+#else /* The above does not return correct error code to DOS
+ - resulting in reporting the error as memory fault!
+ Here is fix which I suppose to return correct error: */
+ if (ret != -1) return TRUE; /* no error */
+ ret = (errno == EAGAIN) ? FILE_LOCK_VIOLATION :
+ (errno == ENOLCK) ? SHARING_BUF_EXCEEDED :
+ FUNC_NUM_IVALID;
+ SETWORD(&(state->eax), ret); return FALSE;
+#endif
}
break;
case UNLOCK_FILE_REGION: /* 0x0b */
------------------------------------------------------------------------
dosemu-0.98.8/ src/dosext/mfs/mfs.c
case LOCK_FILE_REGION: /* 0x0a */
/* The foll...
/* It manage ...
/* I don't know how to find out from here which DOS is running */
There are two possible formats of LOCK/UNLOCK command: DOS 3.x uses
BX=handle, DOS 4+ uses BL=0 to lock, BL=1 to unlock - it may look like
DOS 3.x call for handle 0 or 1 (assuming BH is 0 - in fact I found it
to be 5C, and handle of 5C00 or 5C01 is highly unlikely ;-), also CX=1
is likely on DOS 4+ and less likely on DOS 3.x) since may assume DOS
3.x for BL>1, 4+ for BX=5C00 or 5C01, or CX=1 and BX=0 or 1, need save
info that one of known formats was recognized, question what to do in
case of BX<=1 before format is recognized - write warning to errlog?
The offset handling is really strange - in case any of 2 top bits is
set they are shifted 2 positions right and or-ed with remaining bits of
the offset (why there is "if" to check them? "or" of 0 is do-nothing).
...
return ret != -1 ? TRUE : FALSE;
This is what must be changed to fix the bug: best is to examine errno.
I hope invalid handle is detected earlier, since the code may be:
if (ret != -1) return TRUE;
ret = (errno==EAGAIN) ? FILE_LOCK_VIOLATION :
(errno==ENOLCK) ? SHARING_BUF_EXCEEDED : FUNC_NUM_IVALID;
SETWORD(&(state->eax), ret); return FALSE;