[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v1 7/7] tools/ocaml/libs/eventchn: do not leak event channels and OCaml 5.0 compat


  • To: Andrew Cooper <Andrew.Cooper3@xxxxxxxxxx>
  • From: Edwin Torok <edvin.torok@xxxxxxxxxx>
  • Date: Mon, 8 Aug 2022 08:28:50 +0000
  • Accept-language: en-GB, en-US
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=EeFgg0PZLXmc11B2lFa4DrrH8M4ggU2n2VlpXlpGeq4=; b=SZDSkwruBzErxyuipnYheSxXt+Ni9ljNr9v+WlnsoEnjOu4zvRGVeoze3b7EcnUj/3yPvbIYBpd8DCBA1KArHgwk+yqnbFdVUSPntxG96EDqr7E3kLQmQWTph0tNuDubMgGZjPpCPMv1igDTbdZp1HUEVXQMa3J4C6NvD89MD/yZW5z0p7GYD7Kw0z6GbVRJ7HC7bdOGCpJi1oR76JwngthLwRtUbvZlYNOlF1YXlxLkohuIXK9/fUjbfDptQedPh9zkhJ9fMMXg/IFOF9gtNaCQBAQV1wKa4b8YtQUzalAjEfl8BY616Itc//kC38AMmNKXZZzH7i10McZxEmCoCg==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=mAOxjlm3BiU5MDAOt3z7relYO6pGn4CDLJharg+cVO6VJTiXRiauaBvzLtVbgM3yOJNUcDe7S9N/GXnCuiK9PWEpDXDS9/c6FzfKjQzdVbp0XHkOgsRh9Jj6hLYvoeHoN3m3Y0fxT4DMLtPdcPuZt9m8V4zsno2B58elPMRLgDjQ6lNNiL5w89N13ybsSeyQDVvbKBwKaU8yNVdI2uPjrhucHSLA0tHbWVQS1R6/Mt/LB3EgTq56olgvvPGReEOIXH9tc+lUZjtDt0VoDmqyflr/qpIFqoSv9rPZDPEpGP55lFpsYqigeF+9zWESF0K6tnJ0zpE9kjEZ0k3piIjAvA==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Cc: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>, Christian Lindig <christian.lindig@xxxxxxxxxx>, David Scott <dave@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, Anthony Perard <anthony.perard@xxxxxxxxxx>
  • Delivery-date: Mon, 08 Aug 2022 08:29:26 +0000
  • Ironport-data: A9a23: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
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
  • Thread-index: AQHYo3Q0OnbES2PbE0uxc/5mBalu0q2gpUyAgAQVkQA=
  • Thread-topic: [PATCH v1 7/7] tools/ocaml/libs/eventchn: do not leak event channels and OCaml 5.0 compat


> On 5 Aug 2022, at 19:06, Andrew Cooper <Andrew.Cooper3@xxxxxxxxxx> wrote:
> 
> On 29/07/2022 18:53, Edwin Török wrote:
>> Add a finalizer on the event channel value, so that it calls
>> `xenevtchn_close` when the value would be GCed.
>> 
>> In practice oxenstored seems to be the only user of this,
>> and it creates a single global event channel only,
>> but freeing this could still be useful when run with OCAMLRUNPARAM=c
>> 
>> The code was previously casting a C pointer to an OCaml value,
>> which should be avoided: OCaml 5.0 won't support it.
>> (all "naked" C pointers must be wrapped inside an OCaml value,
>> either an Abstract tag, or Nativeint, see the manual
>> https://ocaml.org/manual/intfc.html#ss:c-outside-head)
>> 
>> Signed-off-by: Edwin Török <edvin.torok@xxxxxxxxxx>
> 
> So while this looks like a good improvement, don't we need to do it for
> all libraries, not just evtchn?
> 
> It doesn't look as if Ocaml 5.0 is very far away.

There are 2 ways to make it safe: use a block with Abstract_tag, or a block 
with Custom_tag:
https://v2.ocaml.org/manual/intfc.html#ss:c-outside-head

(technically it only ever was safe to use naked pointers for word-aligned 
pointers previously, although malloc usually
 ensures some minimal alignment).

There is a mode where the runtime can warn on stderr whenever naked pointers 
are used (there is an opam switch for it,
or one can specify a flag during the compiler build time), but it only does so 
when that codepath is hit,
not at build/link time.

A quick look at the libs:
* libs/mmap: uses Abstract_tag
* eventchn: fixed here to use Custom_tag
* libs/xc: needs fixing, stub_xc_interface_open
* libs/xl: uses Custom_tag (although it has other known issues (it should never 
use caml_callbackN directly, but use caml_callbackN_exn, see 
https://v2.ocaml.org/manual/intfc.html#ss:c-callbacks)
* libs/xentoollog: uses Custom_tag

So we need a patch for libs/xc.

> 
>> ---
>> tools/ocaml/libs/eventchn/xeneventchn_stubs.c | 29 +++++++++++++++++--
>> 1 file changed, 27 insertions(+), 2 deletions(-)
>> 
>> diff --git a/tools/ocaml/libs/eventchn/xeneventchn_stubs.c 
>> b/tools/ocaml/libs/eventchn/xeneventchn_stubs.c
>> index f889a7a2e4..c0d57e2954 100644
>> --- a/tools/ocaml/libs/eventchn/xeneventchn_stubs.c
>> +++ b/tools/ocaml/libs/eventchn/xeneventchn_stubs.c
>> @@ -33,7 +33,30 @@
>> #include <caml/fail.h>
>> #include <caml/signals.h>
>> 
>> -#define _H(__h) ((xenevtchn_handle *)(__h))
>> +/* We want to close the event channel when it is no longer in use,
>> +   which can only be done safely with a finalizer.
>> +   Event channels are typically long lived, so we don't need tighter 
>> control over resource deallocation.
>> +   Use a custom block
>> +*/
>> +
>> +/* Access the xenevtchn_t* part of the OCaml custom block */
>> +#define _H(__h) (*((xenevtchn_handle**)Data_custom_val(__h)))
>> +
>> +static void stub_evtchn_finalize(value v)
>> +{
>> +    /* docs say to not use any CAMLparam* macros here */
>> +    xenevtchn_close(_H(v));
>> +}
>> +
>> +static struct custom_operations xenevtchn_ops = {
>> +    "xenevtchn",
>> +    stub_evtchn_finalize,
>> +    custom_compare_default, /* raises Failure, cannot compare */
>> +    custom_hash_default, /* ignored */
>> +    custom_serialize_default, /* raises Failure, can't serialize */
>> +    custom_deserialize_default, /* raises Failure, can't deserialize */
>> +    custom_compare_ext_default /* raises Failure */
> 
> This wants to gain a trailing comma.
> 
>> +};
>> 
>> CAMLprim value stub_eventchn_init(void)
>> {
>> @@ -48,7 +71,9 @@ CAMLprim value stub_eventchn_init(void)
>>      if (xce == NULL)
>>              caml_failwith("open failed");
>> 
>> -    result = (value)xce;
>> +    /* contains file descriptors, trigger full GC at least every 128 
>> allocations */
>> +    result = caml_alloc_custom(&xenevtchn_ops, sizeof(xce), 1, 128);
> 
> The memory allocated for xce is tiny (48 bytes) and invariant for the
> lifetime of the evtchn object, which we've already established tends to
> operate as a singleton anyway.
> 
> Don't we want to use the recommended 0 and 1 here?

It is not just about the memory itself, but also about the file descriptors: 
those are a limited resource,
and if we use the 0 and 1 it means that this will be garbage collected very 
infrequently since the allocation itself is very small,
and you could potentially run out of file descriptors if you keep opening new 
event channels.
Notice there is no API for the user to close the event channel, so it has to 
rely on the GC, which is not ideal.

The mirage version of the eventchn lib does provide a close function: 
https://github.com/mirage/ocaml-evtchn/blob/main/lib/eventchn.mli,
although its implementation just leaks it (to avoid use-after-free): 
https://github.com/mirage/ocaml-evtchn/blob/main/lib/eventchn.ml#L42

Are event channel always expected to be singletons, is there a valid use case 
where you'd want more than 1 event channel/process?

Best regards,
--Edwin

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.