Skip to content
  • Ian Jackson's avatar
    libxl: enforce prohibitions of internal callers · 4b34f574
    Ian Jackson authored
    
    
    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: default avatarIan Jackson <ian.jackson@eu.citrix.com>
    Cc: Roger Pau Monne <roger.pau@citrix.com>
    Acked-by: default avatarIan Campbell <ian.campbell@citrix.com>
    Committed-by: default avatarIan Campbell <ian.campbell@citrix.com>
    4b34f574