>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;

Reply via email to