[racket] distributed place messages: "write" isn't atomic

From: Tim Brown (tim.brown at cityc.co.uk)
Date: Fri Mar 20 06:14:12 EDT 2015

I have written a remote-server (as in
racket/place/define-remote-server), which I am then trying to use from a
web-server. The remote-server is running on a remote node (which is, in
fact, localhost).

The arguments to the RPC calls (from define-rpc) are fairly large
(including a serialised "request" object).

When RPC calls are made one at a time, the system works. However, when
enough stress is put upon the system (by me bashing at the refresh on
my web browser) to make two "simultaneous" RPC calls, the following
exception is thrown up:

------------------------------------------------------------------
UNKNOWN::2171: read: invalid structure description in `#s' form

   context...:
 
/usr/local/racket/share/pkgs/distributed-places-lib/racket/place/distributed.rkt:392:8: 
loop
    [my call stack]
    [my web-server].rkt:58:0: start
 
/usr/local/racket/share/pkgs/web-server-lib/web-server/dispatchers/dispatch-servlets.rkt:58:2
    /usr/local/racket/collects/racket/private/more-scheme.rkt:162:2: 
select-handler/no-breaks
 
/usr/local/racket/share/pkgs/web-server-lib/web-server/private/dispatch-server-unit.rkt:112:8
Servlet (@ /servlets/standalone.rkt) exception:
dcgm-type: contract violation
   expected: dcgm?
   given: 'cdgm
------------------------------------------------------------------

It seems that the RPC packets are overlapping. They are posted using
the following calls. Following the *channel-put call in the source
(distributed.rkt):

  1529:  *channel-put
   411:  place-socket-bridge% put-msg
   716:  sconn-write-flush
   769:  socket-connection% _write-flush
   157:  write-flush
   161:  write

That 'write' is bound to the 'write' from racket/base.

OK... back to my RPC call... the message I'm sending is composite; it is
a list of strings amongst others -- and I assume that the write is
written recursively to low-level output the components in parts. In
other words the write to the remote host is non-atomic, and not
synchronised.

My web-server (the Racket web-server) is multi-threaded, so I need some
means of synchronising this RPC write.

First -- am I missing something? (Given as the answer is usually yes,
it's a question well worth asking)

Has anyone else done this/encountered this?

Will a write of a single string suffer this?
   In fact, on closer inspection - no matter what *I* do to make my
   message atomic, sconn-write-flush writes a structure which I assume
   will be written in bits.

Would a semaphore (or similar) around sconn-write-flush be the right
place/time for synchronising messages.

Also -- I notice that write-flush is defined as:

(define (write-flush msg [p (current-output-port)])
   (flush-output)
   (write msg p)
   (flush-output p))

Should that first flush-output be on p?

Thanks, in advance, for your help with this.

Regards,

Tim

-- 
Tim Brown CEng MBCS <tim.brown at cityc.co.uk>
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
                 City Computing Limited · www.cityc.co.uk
       City House · Sutton Park Rd · Sutton · Surrey · SM1 2AE · GB
                 T:+44 20 8770 2110 · F:+44 20 8770 2130
────────────────────────────────────────────────────────────────────────
City Computing Limited registered in London No:1767817.
Registered Office: City House, Sutton Park Road, Sutton, Surrey, SM1 2AE
VAT No: GB 918 4680 96

Posted on the users mailing list.