diff options
author | Ian Jackson <Ian.Jackson@eu.citrix.com> | 2012-08-01 12:46:52 +0100 |
---|---|---|
committer | Ian Jackson <Ian.Jackson@eu.citrix.com> | 2012-08-01 12:46:52 +0100 |
commit | 2862bf5b6c81979596ce84e53e7cc1d88be9dcd2 (patch) | |
tree | b47811cbf0ee80acf6395c072efa42007572999f /tools/libxl/libxl_event.h | |
parent | f47d809c449a105b77fbc5fc6f058b24f8537a94 (diff) | |
download | xen-2862bf5b6c81979596ce84e53e7cc1d88be9dcd2.tar.gz xen-2862bf5b6c81979596ce84e53e7cc1d88be9dcd2.tar.bz2 xen-2862bf5b6c81979596ce84e53e7cc1d88be9dcd2.zip |
libxl: enforce prohibitions of internal callers
libxl_internal.h says:
* Functions using LIBXL__INIT_EGC may *not* generally be called from
* within libxl, because libxl__egc_cleanup may call back into the
* application. ...
and
* ... [Functions which take an ao_how] MAY NOT
* be called from inside libxl, because they can cause reentrancy
* callbacks.
However, this was not enforced. Particularly the latter restriction
is easy to overlook, especially since during the transition period to
the new event system we have bent this rule a couple of times, and the
bad pattern simply involves passing 0 or NULL for the ao_how.
So use the compiler to enforce this property, as follows:
- Mark all functions which take a libxl_asyncop_how, or which
use EGC_INIT or LIBXL__INIT_EGC, with a new annotation
LIBXL_EXTERNAL_CALLERS_ONLY in the public header.
- Change the documentation comment for asynch operations and egcs to
say that this should always be done.
- Arrange that if libxl.h is included via libxl_internal.h,
LIBXL_EXTERNAL_CALLERS_ONLY expands to __attribute__((warning(...))),
which generates a message like this:
libxl.c:1772: warning: call to 'libxl_device_disk_remove'
declared with attribute warning:
may not be called from within libxl
Otherwise, the annotation expands to nothing, so external
callers are unaffected.
- Forbid inclusion of both libxl.h and libxl_internal.h unless
libxl_internal.h came first, so that the above check doesn't have
any loopholes. Files which include libxl_internal.h should not
include libxl.h as well.
This is enforced explicitly using #error. However, in practice
with the current tree it just changes the error message when this
mistake is made; otherwise we would carry on to immediately
following #define which would cause the compiler to complain that
LIBXL_EXTERNAL_CALLERS_ONLY was redefined. Then the developer
might be tempted to add a #ifndef which would be wrong - it would
leave the affected translation unit unprotected by the new
enforcement regime. So let's be explicit.
- Fix the one source of files which violate the above principle, the
output from the idl compiler, by removing the redundant inclusion
of libxl.h from the output.
Also introduce a new script "check-libxl-api-rules" which contains
some ad-hoc regexps to spot and complain when libxl.h contains
functions which mention libxl_asyncop_how but not
LIBXL_EXTERNAL_CALLERS_ONLY. This isn't a full C parser but is likely
to get the common cases right and err on the side of complaining.
While we are here, the invocation of perl for the bsd queue.h seddery
to $(PERL).
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Roger Pau Monne <roger.pau@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
Committed-by: Ian Campbell <ian.campbell@citrix.com>
Diffstat (limited to 'tools/libxl/libxl_event.h')
-rw-r--r-- | tools/libxl/libxl_event.h | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/tools/libxl/libxl_event.h b/tools/libxl/libxl_event.h index 713d96d1ed..3344bc8b9a 100644 --- a/tools/libxl/libxl_event.h +++ b/tools/libxl/libxl_event.h @@ -37,7 +37,8 @@ typedef int libxl_event_predicate(const libxl_event*, void *user); int libxl_event_check(libxl_ctx *ctx, libxl_event **event_r, uint64_t typemask, - libxl_event_predicate *predicate, void *predicate_user); + libxl_event_predicate *predicate, void *predicate_user) + LIBXL_EXTERNAL_CALLERS_ONLY; /* Searches for an event, already-happened, which matches typemask * and predicate. predicate==0 matches any event. * libxl_event_check returns the event, which must then later be @@ -48,7 +49,8 @@ int libxl_event_check(libxl_ctx *ctx, libxl_event **event_r, int libxl_event_wait(libxl_ctx *ctx, libxl_event **event_r, uint64_t typemask, - libxl_event_predicate *predicate, void *predicate_user); + libxl_event_predicate *predicate, void *predicate_user) + LIBXL_EXTERNAL_CALLERS_ONLY; /* Like libxl_event_check but blocks if no suitable events are * available, until some are. Uses libxl_osevent_beforepoll/ * _afterpoll so may be inefficient if very many domains are being @@ -256,7 +258,8 @@ struct pollfd; */ int libxl_osevent_beforepoll(libxl_ctx *ctx, int *nfds_io, struct pollfd *fds, int *timeout_upd, - struct timeval now); + struct timeval now) + LIBXL_EXTERNAL_CALLERS_ONLY; /* nfds and fds[0..nfds] must be from the most recent call to * _beforepoll, as modified by poll. (It is therefore not possible @@ -271,7 +274,8 @@ int libxl_osevent_beforepoll(libxl_ctx *ctx, int *nfds_io, * libxl_event_check. */ void libxl_osevent_afterpoll(libxl_ctx *ctx, int nfds, const struct pollfd *fds, - struct timeval now); + struct timeval now) + LIBXL_EXTERNAL_CALLERS_ONLY; typedef struct libxl_osevent_hooks { @@ -357,14 +361,16 @@ void libxl_osevent_register_hooks(libxl_ctx *ctx, */ void libxl_osevent_occurred_fd(libxl_ctx *ctx, void *for_libxl, - int fd, short events, short revents); + int fd, short events, short revents) + LIBXL_EXTERNAL_CALLERS_ONLY; /* Implicitly, on entry to this function the timeout has been * deregistered. If _occurred_timeout is called, libxl will not * call timeout_deregister; if it wants to requeue the timeout it * will call timeout_register again. */ -void libxl_osevent_occurred_timeout(libxl_ctx *ctx, void *for_libxl); +void libxl_osevent_occurred_timeout(libxl_ctx *ctx, void *for_libxl) + LIBXL_EXTERNAL_CALLERS_ONLY; /*======================================================================*/ @@ -506,7 +512,8 @@ void libxl_childproc_setmode(libxl_ctx *ctx, const libxl_childproc_hooks *hooks, * certainly need to use the self-pipe trick (or a working pselect or * ppoll) to implement this. */ -int libxl_childproc_reaped(libxl_ctx *ctx, pid_t, int status); +int libxl_childproc_reaped(libxl_ctx *ctx, pid_t, int status) + LIBXL_EXTERNAL_CALLERS_ONLY; /* |