Cross-VM method for sending any input port to C runtime?

43 views
Skip to first unread message

Sage Gerard

unread,
May 23, 2021, 10:57:48 AM5/23/21
to Racket Users

Hi all,

I have a C shared library exposing a simplified interface for computing message digests. Here's a `while` that reads bytes using a callback.

https://github.com/zyrolasting/xiden/blob/libcrypto/crypto/crypto.c#L46

A compatible callback provided by Racket might look like this.

(λ (buf size)
  (let ([bytes-read (read-bytes! buf (sync variant))])
    (if (eof-object? bytes-read) -1 bytes-read)))

I'm also unsure if jumping between the Racket and C runtimes add much overhead, but I did it because it looks like `unsafe-port->file-descriptor` will only function as expected for file ports.

Is there a cross-VM way to pass an arbitrary input port to the C runtime (e.g. via open-input-bytes), such that the C runtime can read bytes on its own?

--
~slg

Matthew Flatt

unread,
May 23, 2021, 7:57:11 PM5/23/21
to Sage Gerard, Racket Users
At Sun, 23 May 2021 14:57:42 +0000, Sage Gerard wrote:
> Is there a cross-VM way to pass an arbitrary input port to the C
> runtime (e.g. via open-input-bytes), such that the C runtime can read
> bytes on its own?

No, not unless you know that the port's implementation is sufficiently
constrained. In general, reading from a port can involve thread
switches and synchronization, and those are not allowed in callbacks
from foreign libraries.

(BC doesn't prohibit non-atomic callbacks as aggressively as CS, but
interacting with the Racket thread scheduler from a callback can go
wrong in various ways with BC, too.)


Matthew

Philip McGrath

unread,
May 23, 2021, 8:45:44 PM5/23/21
to Matthew Flatt, Sage Gerard, Racket Users
On Sun, May 23, 2021 at 7:57 PM Matthew Flatt <mfl...@cs.utah.edu> wrote:
At Sun, 23 May 2021 14:57:42 +0000, Sage Gerard wrote:
> Is there a cross-VM way to pass an arbitrary input port to the C
> runtime (e.g. via open-input-bytes), such that the C runtime can read
> bytes on its own?

No, not unless you know that the port's implementation is sufficiently
constrained. In general, reading from a port can involve thread
switches and synchronization, and those are not allowed in callbacks
from foreign libraries.

Off hand, I think some some version of "sanitizing" an arbitrary port for use from C is used by:
  • `racket/system` (here and here), where the implementation comes from `racket/private/streams`;
  • `racket/draw`, for the various parts of Cairo that can read from or write to ports, in `racket/draw/unsafe/callback` (and maybe something similar in `racket/draw/private/write-bytes`?); and
  • `readline`, which uses callbacks rather than creating file-stream ports.
Would it make sense to expose some part of this functionality as a new primitive?

(I'm not familiar with all of the constraints in these use-cases: maybe they're different enough that the answer is "no".)

-Philip

Sage Gerard

unread,
May 27, 2021, 4:24:39 PM5/27/21
to racket...@googlegroups.com

I'm not sure, but I think I can be content with passing Racket bytes across the foreign interface boundary for the C runtime to use given the u8vector equivalence. Only thing I'm not clear on: Is it a good idea for me to designate the byte string as a  _gcpointer on the "*" marked line, or does it not matter?

(define-ffi-definer define-ff (ffi-lib doesnt-matter))
(define-ff fill_up (_fun _pointer _int -> _void)) ; *
(define size 2)
(define buffer
(make-bytes size))
(fill_up buffer size)

--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/010001799bd5ab46-d39f83a5-bb2d-49e5-8ce2-3315307742ac-000000%40email.amazonses.com.
--
~slg
Reply all
Reply to author
Forward
0 new messages