[MUD-Dev] NWN gets more MUD-like (again)

Sean Kelly sean at ffwd.cx
Wed Feb 5 08:57:18 New Zealand Daylight Time 2003

Smith, David (Lynchburg) wrote:

> 3. The wrapper process must now "discover" the memory segment used
> by the server process for the "large blocks of memory" allocated
> by the script. I can see two ways to do this, all with attendant
> advantages and disadvantages.

>      b. (most likely--rather, what I would try) The wrapping
>      process calls WaitForDebugEvent, dispatching the events
>      generated by the server process internally. The script, after
>      allocating, and writing the memory, does something to raise a
>      continuable exception (integeroverflow perhaps?). Mind you,
>      this can be an exception _handled_ as an exception by the nwn
>      scripting engine, provided that it's handled by a catch-type
>      mechanism.  No data on that at the moment, if the script
>      interpreter catches the attempt to cause an exception prior
>      to doing so, this will not work. If it does work, an
>      exception is raised as a debug event, tripping the wrapping
>      process. When the system notifies the debugger of a debugging
>      event, it also suspends all threads in the affected
>      process. The wrapping process then scans for a special byte
>      pattern to establish the location of the memory segments
>      (this is only done once, or as an error recovery path if the
>      segments are re-allocated, more later). After finding the
>      memory segment, thewrapping proces calls ContinueDebugEvent,
>      un-suspending all threads in the server process, and
>      maintaining the memory offset.

> **Discussion :

> I hope that 3.b is a useable mechanism as it induces a lower
> constant overhead. Almost certainly, the wrapping process is using
> the operating system to suspend all threads in the server process
> as a side effect of a debug event being dispatched. Since that
> overhead is already present, the additional overhead of the
> wrapping process having to _cause_ the debug event in the server
> process (via a call to DebugBreakProcess as in 3.a), versus having
> the already-executing scripting engine cause the debug event (via
> some continuable exception raising mechanism like integer
> overflow--assuming, and making possibly an ass out of myself--that
> integer overflow is a continuable exception).

I'm pretty new to writing a debugger, so I asked a few questions on
the MS forums after looking at the DB code.  From what I can tell,
the script never explicitly signals the wrapper process in any way.
it writes data out to the memory block and the next instruction is
to read it back in again.  From what I found out, it is possible to
set a breakpoint on a memory segment is done by manipulating the
debug registers in the thread context of the debug process.

> However, the mechanism likely used to suspend the server has the
> following easily identified drawback: All threads in the server
> are suspended. This _does_ guarantee that no code will execute
> while the wrapping process handles the database query; however, it
> may be overkill.

I agree.  Especially for long queries.

> Instead, it should be possible to use method 3.b above, retrieving
> a handle to _only_the_thread_that_raised_the_debug_event.  This
> thread is _almost_certainly_ the only thread executing within the
> script interpreter (aside from my vast doubts that Bioware wrote a
> multithread-capable scripting language, note the empirical
> evidence, when a script is taking _far_ too long to execute the
> entire server will eventually feel the lag). With that thread
> handle, immediately increment the "script interpetter thread"'s
> suspend count by calling SuspendThread, then, immediately call
> ContinueDebugEvent, the remaining application threads should be
> released, and the "script interpretter thread" will remain
> suspended (still has a suspension count > 0). The wrapping process
> should then service the database request with all possible speed,
> and upon completion, call ResumeThread to decrement the "script
> interpretter thread" suspension count. The script interpretter
> should continue execution.

Interesting idea.  The problem, then, is how to generate an
exception from within NWScript.  I *have* managed to crash the game
before from bad script calls, but I think simple things like divide
by zero aren't an option.  Still, it'd definately worth some

> Anticipated Questions:

>   Q: Is it really necessary to argue about half-seconds here in
>   "constant" overhead for each database hit?

>     A: Absolutely, if every persistence call in every script is
>     going to cause every thread to block, even for a few seconds,
>     the results versus latency and throughput could _easily_ cause
>     packets to back up, and eventually be lost if they can't be
>     serviced fast enough when the server is resumed from
>     suspension.

Definately.  I've already asked the developer of the DB system about
the possibility of signaling an operation early, say at the
beginning of a script call, and checking the return value at the
end.  This might save a few milliseconds in terms of how long the
engine is suspended.

The add-on was released under the GPL so the wrapper code will
eventually be released.  At that point I hope some tweaking will be

Unfortunately, all of this could be avoided if we were given some
method for exposing new NWScript functions in user-written dynamic
libraries. I haven't heard a convincing argument against why this
feature hasn't been offered, and continue to hope that it will
someday.  I know that the possibility of malicious code becomes an
issue, but this is something every mod community addresses.


MUD-Dev mailing list
MUD-Dev at kanga.nu

More information about the MUD-Dev mailing list