Missing virt-df/.depend.
[virt-top.git] / libvirt / libvirt_c.c
old mode 100644 (file)
new mode 100755 (executable)
index a2bb1ad..4ae121c
 #include <caml/memory.h>
 #include <caml/misc.h>
 #include <caml/mlvalues.h>
+#include <caml/signals.h>
 
 static char *Optstring_val (value strv);
 typedef value (*Val_ptr_t) (void *);
 static value Val_opt (void *ptr, Val_ptr_t Val_ptr);
 /*static value option_default (value option, value deflt);*/
-static value _raise_virterror (virConnectPtr conn, const char *fn);
+static void _raise_virterror (virConnectPtr conn, const char *fn);
+static void not_supported (const char *fn);
 static value Val_virterror (virErrorPtr err);
 
+/* Use this around synchronous libvirt API calls to release the OCaml
+ * lock, allowing other threads to run simultaneously.  'code' must not
+ * perform any caml_* calls, run any OCaml code, or raise any exception.
+ * http://web.archive.org/web/20030521020915/http://caml.inria.fr/archives/200106/msg00199.html
+ */
+#define NONBLOCKING(code)                      \
+  do {                                         \
+    caml_enter_blocking_section ();            \
+    code;                                      \
+    caml_leave_blocking_section ();            \
+  } while (0)
+
+/* Check error condition from a libvirt function, and automatically raise
+ * an exception if one is found.
+ */
 #define CHECK_ERROR(cond, conn, fn) \
   do { if (cond) _raise_virterror (conn, fn); } while (0)
 
-#define NOT_SUPPORTED(fn)                      \
-  caml_invalid_argument (fn " not supported")
-
 /* For more about weak symbols, see:
  * http://kolpackov.net/pipermail/notes/2004-March/000006.html
  * We are using this to do runtime detection of library functions
@@ -65,7 +79,7 @@ static value Val_virterror (virErrorPtr err);
 
 #ifdef HAVE_WEAK_SYMBOLS
 #define WEAK_SYMBOL_CHECK(sym)                         \
-  do { if (!sym) NOT_SUPPORTED(#sym); } while (0)
+  do { if (!sym) not_supported(#sym); } while (0)
 #else
 #define WEAK_SYMBOL_CHECK(sym)
 #endif /* HAVE_WEAK_SYMBOLS */
@@ -140,7 +154,7 @@ ocaml_libvirt_get_version (value driverv, value unit)
   int r;
 
   typeVer_ptr = driver ? &typeVer : NULL;
-  r = virGetVersion (&libVer, driver, typeVer_ptr);
+  NONBLOCKING (r = virGetVersion (&libVer, driver, typeVer_ptr));
   CHECK_ERROR (r == -1, NULL, "virGetVersion");
 
   rv = caml_alloc_tuple (2);
@@ -236,7 +250,7 @@ ocaml_libvirt_connect_open (value namev, value unit)
   const char *name = Optstring_val (namev);
   virConnectPtr conn;
 
-  conn = virConnectOpen (name);
+  NONBLOCKING (conn = virConnectOpen (name));
   CHECK_ERROR (!conn, NULL, "virConnectOpen");
 
   rv = Val_connect (conn);
@@ -252,7 +266,7 @@ ocaml_libvirt_connect_open_readonly (value namev, value unit)
   const char *name = Optstring_val (namev);
   virConnectPtr conn;
 
-  conn = virConnectOpenReadOnly (name);
+  NONBLOCKING (conn = virConnectOpenReadOnly (name));
   CHECK_ERROR (!conn, NULL, "virConnectOpen");
 
   rv = Val_connect (conn);
@@ -267,7 +281,7 @@ ocaml_libvirt_connect_close (value connv)
   virConnectPtr conn = Connect_val (connv);
   int r;
 
-  r = virConnectClose (conn);
+  NONBLOCKING (r = virConnectClose (conn));
   CHECK_ERROR (r == -1, conn, "virConnectClose");
 
   /* So that we don't double-free in the finalizer: */
@@ -284,7 +298,7 @@ ocaml_libvirt_connect_get_type (value connv)
   virConnectPtr conn = Connect_val (connv);
   const char *r;
 
-  r = virConnectGetType (conn);
+  NONBLOCKING (r = virConnectGetType (conn));
   CHECK_ERROR (!r, conn, "virConnectGetType");
 
   rv = caml_copy_string (r);
@@ -299,7 +313,7 @@ ocaml_libvirt_connect_get_version (value connv)
   unsigned long hvVer;
   int r;
 
-  r = virConnectGetVersion (conn, &hvVer);
+  NONBLOCKING (r = virConnectGetVersion (conn, &hvVer));
   CHECK_ERROR (r == -1, conn, "virConnectGetVersion");
 
   CAMLreturn (Val_int (hvVer));
@@ -315,14 +329,14 @@ ocaml_libvirt_connect_get_hostname (value connv)
   char *r;
 
   WEAK_SYMBOL_CHECK (virConnectGetHostname);
-  r = virConnectGetHostname (conn);
+  NONBLOCKING (r = virConnectGetHostname (conn));
   CHECK_ERROR (!r, conn, "virConnectGetHostname");
 
   rv = caml_copy_string (r);
   free (r);
   CAMLreturn (rv);
 #else
-  NOT_SUPPORTED ("virConnectGetHostname");
+  not_supported ("virConnectGetHostname");
 #endif
 }
 
@@ -336,14 +350,14 @@ ocaml_libvirt_connect_get_uri (value connv)
   char *r;
 
   WEAK_SYMBOL_CHECK (virConnectGetURI);
-  r = virConnectGetURI (conn);
+  NONBLOCKING (r = virConnectGetURI (conn));
   CHECK_ERROR (!r, conn, "virConnectGetURI");
 
   rv = caml_copy_string (r);
   free (r);
   CAMLreturn (rv);
 #else
-  NOT_SUPPORTED ("virConnectGetURI");
+  not_supported ("virConnectGetURI");
 #endif
 }
 
@@ -355,7 +369,7 @@ ocaml_libvirt_connect_get_max_vcpus (value connv, value typev)
   const char *type = Optstring_val (typev);
   int r;
 
-  r = virConnectGetMaxVcpus (conn, type);
+  NONBLOCKING (r = virConnectGetMaxVcpus (conn, type));
   CHECK_ERROR (r == -1, conn, "virConnectGetMaxVcpus");
 
   CAMLreturn (Val_int (r));
@@ -370,7 +384,7 @@ ocaml_libvirt_connect_list_domains (value connv, value iv)
   int i = Int_val (iv);
   int ids[i], r;
 
-  r = virConnectListDomains (conn, ids, i);
+  NONBLOCKING (r = virConnectListDomains (conn, ids, i));
   CHECK_ERROR (r == -1, conn, "virConnectListDomains");
 
   rv = caml_alloc (r, 0);
@@ -387,7 +401,7 @@ ocaml_libvirt_connect_num_of_domains (value connv)
   virConnectPtr conn = Connect_val (connv);
   int r;
 
-  r = virConnectNumOfDomains (conn);
+  NONBLOCKING (r = virConnectNumOfDomains (conn));
   CHECK_ERROR (r == -1, conn, "virConnectNumOfDomains");
 
   CAMLreturn (Val_int (r));
@@ -401,7 +415,7 @@ ocaml_libvirt_connect_get_capabilities (value connv)
   virConnectPtr conn = Connect_val (connv);
   char *r;
 
-  r = virConnectGetCapabilities (conn);
+  NONBLOCKING (r = virConnectGetCapabilities (conn));
   CHECK_ERROR (!r, conn, "virConnectGetCapabilities");
 
   rv = caml_copy_string (r);
@@ -417,7 +431,7 @@ ocaml_libvirt_connect_num_of_defined_domains (value connv)
   virConnectPtr conn = Connect_val (connv);
   int r;
 
-  r = virConnectNumOfDefinedDomains (conn);
+  NONBLOCKING (r = virConnectNumOfDefinedDomains (conn));
   CHECK_ERROR (r == -1, conn, "virConnectNumOfDefinedDomains");
 
   CAMLreturn (Val_int (r));
@@ -433,7 +447,7 @@ ocaml_libvirt_connect_list_defined_domains (value connv, value iv)
   char *names[i];
   int r;
 
-  r = virConnectListDefinedDomains (conn, names, i);
+  NONBLOCKING (r = virConnectListDefinedDomains (conn, names, i));
   CHECK_ERROR (r == -1, conn, "virConnectListDefinedDomains");
 
   rv = caml_alloc (r, 0);
@@ -453,7 +467,7 @@ ocaml_libvirt_connect_num_of_networks (value connv)
   virConnectPtr conn = Connect_val (connv);
   int r;
 
-  r = virConnectNumOfNetworks (conn);
+  NONBLOCKING (r = virConnectNumOfNetworks (conn));
   CHECK_ERROR (r == -1, conn, "virConnectNumOfNetworks");
 
   CAMLreturn (Val_int (r));
@@ -469,7 +483,7 @@ ocaml_libvirt_connect_list_networks (value connv, value iv)
   char *names[i];
   int r;
 
-  r = virConnectListNetworks (conn, names, i);
+  NONBLOCKING (r = virConnectListNetworks (conn, names, i));
   CHECK_ERROR (r == -1, conn, "virConnectListNetworks");
 
   rv = caml_alloc (r, 0);
@@ -489,7 +503,7 @@ ocaml_libvirt_connect_num_of_defined_networks (value connv)
   virConnectPtr conn = Connect_val (connv);
   int r;
 
-  r = virConnectNumOfDefinedNetworks (conn);
+  NONBLOCKING (r = virConnectNumOfDefinedNetworks (conn));
   CHECK_ERROR (r == -1, conn, "virConnectNumOfDefinedNetworks");
 
   CAMLreturn (Val_int (r));
@@ -505,7 +519,7 @@ ocaml_libvirt_connect_list_defined_networks (value connv, value iv)
   char *names[i];
   int r;
 
-  r = virConnectListDefinedNetworks (conn, names, i);
+  NONBLOCKING (r = virConnectListDefinedNetworks (conn, names, i));
   CHECK_ERROR (r == -1, conn, "virConnectListDefinedNetworks");
 
   rv = caml_alloc (r, 0);
@@ -527,7 +541,7 @@ ocaml_libvirt_connect_get_node_info (value connv)
   virNodeInfo info;
   int r;
 
-  r = virNodeGetInfo (conn, &info);
+  NONBLOCKING (r = virNodeGetInfo (conn, &info));
   CHECK_ERROR (r == -1, conn, "virNodeGetInfo");
 
   rv = caml_alloc (8, 0);
@@ -553,13 +567,13 @@ ocaml_libvirt_connect_node_get_free_memory (value connv)
   unsigned long long r;
 
   WEAK_SYMBOL_CHECK (virNodeGetFreeMemory);
-  r = virNodeGetFreeMemory (conn);
+  NONBLOCKING (r = virNodeGetFreeMemory (conn));
   CHECK_ERROR (r == 0, conn, "virNodeGetFreeMemory");
 
   rv = caml_copy_int64 ((int64) r);
   CAMLreturn (rv);
 #else
-  NOT_SUPPORTED ("virNodeGetFreeMemory");
+  not_supported ("virNodeGetFreeMemory");
 #endif
 }
 
@@ -577,7 +591,7 @@ ocaml_libvirt_connect_node_get_cells_free_memory (value connv,
   unsigned long long freemems[max];
 
   WEAK_SYMBOL_CHECK (virNodeGetCellsFreeMemory);
-  r = virNodeGetCellsFreeMemory (conn, freemems, start, max);
+  NONBLOCKING (r = virNodeGetCellsFreeMemory (conn, freemems, start, max));
   CHECK_ERROR (r == -1, conn, "virNodeGetCellsFreeMemory");
 
   rv = caml_alloc (r, 0);
@@ -588,7 +602,7 @@ ocaml_libvirt_connect_node_get_cells_free_memory (value connv,
 
   CAMLreturn (rv);
 #else
-  NOT_SUPPORTED ("virNodeGetCellsFreeMemory");
+  not_supported ("virNodeGetCellsFreeMemory");
 #endif
 }
 
@@ -601,7 +615,7 @@ ocaml_libvirt_domain_create_linux (value connv, value xmlv)
   char *xml = String_val (xmlv);
   virDomainPtr r;
 
-  r = virDomainCreateLinux (conn, xml, 0);
+  NONBLOCKING (r = virDomainCreateLinux (conn, xml, 0));
   CHECK_ERROR (!r, conn, "virDomainCreateLinux");
 
   rv = Val_domain (r, connv);
@@ -617,7 +631,7 @@ ocaml_libvirt_domain_lookup_by_id (value connv, value iv)
   int i = Int_val (iv);
   virDomainPtr r;
 
-  r = virDomainLookupByID (conn, i);
+  NONBLOCKING (r = virDomainLookupByID (conn, i));
   CHECK_ERROR (!r, conn, "virDomainLookupByID");
 
   rv = Val_domain (r, connv);
@@ -633,7 +647,7 @@ ocaml_libvirt_domain_lookup_by_uuid (value connv, value uuidv)
   char *uuid = String_val (uuidv);
   virDomainPtr r;
 
-  r = virDomainLookupByUUID (conn, (unsigned char *) uuid);
+  NONBLOCKING (r = virDomainLookupByUUID (conn, (unsigned char *) uuid));
   CHECK_ERROR (!r, conn, "virDomainLookupByUUID");
 
   rv = Val_domain (r, connv);
@@ -649,7 +663,7 @@ ocaml_libvirt_domain_lookup_by_uuid_string (value connv, value uuidv)
   char *uuid = String_val (uuidv);
   virDomainPtr r;
 
-  r = virDomainLookupByUUIDString (conn, uuid);
+  NONBLOCKING (r = virDomainLookupByUUIDString (conn, uuid));
   CHECK_ERROR (!r, conn, "virDomainLookupByUUIDString");
 
   rv = Val_domain (r, connv);
@@ -665,7 +679,7 @@ ocaml_libvirt_domain_lookup_by_name (value connv, value namev)
   char *name = String_val (namev);
   virDomainPtr r;
 
-  r = virDomainLookupByName (conn, name);
+  NONBLOCKING (r = virDomainLookupByName (conn, name));
   CHECK_ERROR (!r, conn, "virDomainLookupByName");
 
   rv = Val_domain (r, connv);
@@ -680,7 +694,7 @@ ocaml_libvirt_domain_destroy (value domv)
   virConnectPtr conn = Connect_domv (domv);
   int r;
 
-  r = virDomainDestroy (dom);
+  NONBLOCKING (r = virDomainDestroy (dom));
   CHECK_ERROR (r == -1, conn, "virDomainDestroy");
 
   /* So that we don't double-free in the finalizer: */
@@ -697,7 +711,7 @@ ocaml_libvirt_domain_free (value domv)
   virConnectPtr conn = Connect_domv (domv);
   int r;
 
-  r = virDomainFree (dom);
+  NONBLOCKING (r = virDomainFree (dom));
   CHECK_ERROR (r == -1, conn, "virDomainFree");
 
   /* So that we don't double-free in the finalizer: */
@@ -714,7 +728,7 @@ ocaml_libvirt_domain_suspend (value domv)
   virConnectPtr conn = Connect_domv (domv);
   int r;
 
-  r = virDomainSuspend (dom);
+  NONBLOCKING (r = virDomainSuspend (dom));
   CHECK_ERROR (r == -1, conn, "virDomainSuspend");
 
   CAMLreturn (Val_unit);
@@ -728,7 +742,7 @@ ocaml_libvirt_domain_resume (value domv)
   virConnectPtr conn = Connect_domv (domv);
   int r;
 
-  r = virDomainResume (dom);
+  NONBLOCKING (r = virDomainResume (dom));
   CHECK_ERROR (r == -1, conn, "virDomainResume");
 
   CAMLreturn (Val_unit);
@@ -743,7 +757,7 @@ ocaml_libvirt_domain_save (value domv, value pathv)
   char *path = String_val (pathv);
   int r;
 
-  r = virDomainSave (dom, path);
+  NONBLOCKING (r = virDomainSave (dom, path));
   CHECK_ERROR (r == -1, conn, "virDomainSave");
 
   CAMLreturn (Val_unit);
@@ -757,7 +771,7 @@ ocaml_libvirt_domain_restore (value connv, value pathv)
   char *path = String_val (pathv);
   int r;
 
-  r = virDomainRestore (conn, path);
+  NONBLOCKING (r = virDomainRestore (conn, path));
   CHECK_ERROR (r == -1, conn, "virDomainRestore");
 
   CAMLreturn (Val_unit);
@@ -772,7 +786,7 @@ ocaml_libvirt_domain_core_dump (value domv, value pathv)
   char *path = String_val (pathv);
   int r;
 
-  r = virDomainCoreDump (dom, path, 0);
+  NONBLOCKING (r = virDomainCoreDump (dom, path, 0));
   CHECK_ERROR (r == -1, conn, "virDomainCoreDump");
 
   CAMLreturn (Val_unit);
@@ -786,7 +800,7 @@ ocaml_libvirt_domain_shutdown (value domv)
   virConnectPtr conn = Connect_domv (domv);
   int r;
 
-  r = virDomainShutdown (dom);
+  NONBLOCKING (r = virDomainShutdown (dom));
   CHECK_ERROR (r == -1, conn, "virDomainShutdown");
 
   CAMLreturn (Val_unit);
@@ -800,7 +814,7 @@ ocaml_libvirt_domain_reboot (value domv)
   virConnectPtr conn = Connect_domv (domv);
   int r;
 
-  r = virDomainReboot (dom, 0);
+  NONBLOCKING (r = virDomainReboot (dom, 0));
   CHECK_ERROR (r == -1, conn, "virDomainReboot");
 
   CAMLreturn (Val_unit);
@@ -815,7 +829,7 @@ ocaml_libvirt_domain_get_name (value domv)
   virConnectPtr conn = Connect_domv (domv);
   const char *r;
 
-  r = virDomainGetName (dom);
+  NONBLOCKING (r = virDomainGetName (dom));
   CHECK_ERROR (!r, conn, "virDomainGetName");
 
   rv = caml_copy_string (r);
@@ -832,7 +846,7 @@ ocaml_libvirt_domain_get_uuid (value domv)
   unsigned char uuid[VIR_UUID_BUFLEN];
   int r;
 
-  r = virDomainGetUUID (dom, uuid);
+  NONBLOCKING (r = virDomainGetUUID (dom, uuid));
   CHECK_ERROR (r == -1, conn, "virDomainGetUUID");
 
   rv = caml_copy_string ((char *) uuid);
@@ -849,7 +863,7 @@ ocaml_libvirt_domain_get_uuid_string (value domv)
   char uuid[VIR_UUID_STRING_BUFLEN];
   int r;
 
-  r = virDomainGetUUIDString (dom, uuid);
+  NONBLOCKING (r = virDomainGetUUIDString (dom, uuid));
   CHECK_ERROR (r == -1, conn, "virDomainGetUUIDString");
 
   rv = caml_copy_string (uuid);
@@ -864,7 +878,7 @@ ocaml_libvirt_domain_get_id (value domv)
   virConnectPtr conn = Connect_domv (domv);
   unsigned int r;
 
-  r = virDomainGetID (dom);
+  NONBLOCKING (r = virDomainGetID (dom));
   /* There's a bug in libvirt which means that if you try to get
    * the ID of a defined-but-not-running domain, it returns -1,
    * and there's no way to distinguish that from an error.
@@ -883,7 +897,7 @@ ocaml_libvirt_domain_get_os_type (value domv)
   virConnectPtr conn = Connect_domv (domv);
   char *r;
 
-  r = virDomainGetOSType (dom);
+  NONBLOCKING (r = virDomainGetOSType (dom));
   CHECK_ERROR (!r, conn, "virDomainGetOSType");
 
   rv = caml_copy_string (r);
@@ -900,7 +914,7 @@ ocaml_libvirt_domain_get_max_memory (value domv)
   virConnectPtr conn = Connect_domv (domv);
   unsigned long r;
 
-  r = virDomainGetMaxMemory (dom);
+  NONBLOCKING (r = virDomainGetMaxMemory (dom));
   CHECK_ERROR (r == 0 /* [sic] */, conn, "virDomainGetMaxMemory");
 
   rv = caml_copy_int64 (r);
@@ -916,7 +930,7 @@ ocaml_libvirt_domain_set_max_memory (value domv, value memv)
   unsigned long mem = Int64_val (memv);
   int r;
 
-  r = virDomainSetMaxMemory (dom, mem);
+  NONBLOCKING (r = virDomainSetMaxMemory (dom, mem));
   CHECK_ERROR (r == -1, conn, "virDomainSetMaxMemory");
 
   CAMLreturn (Val_unit);
@@ -931,7 +945,7 @@ ocaml_libvirt_domain_set_memory (value domv, value memv)
   unsigned long mem = Int64_val (memv);
   int r;
 
-  r = virDomainSetMemory (dom, mem);
+  NONBLOCKING (r = virDomainSetMemory (dom, mem));
   CHECK_ERROR (r == -1, conn, "virDomainSetMemory");
 
   CAMLreturn (Val_unit);
@@ -947,7 +961,7 @@ ocaml_libvirt_domain_get_info (value domv)
   virDomainInfo info;
   int r;
 
-  r = virDomainGetInfo (dom, &info);
+  NONBLOCKING (r = virDomainGetInfo (dom, &info));
   CHECK_ERROR (r == -1, conn, "virDomainGetInfo");
 
   rv = caml_alloc (5, 0);
@@ -969,7 +983,7 @@ ocaml_libvirt_domain_get_xml_desc (value domv)
   virConnectPtr conn = Connect_domv (domv);
   char *r;
 
-  r = virDomainGetXMLDesc (dom, 0);
+  NONBLOCKING (r = virDomainGetXMLDesc (dom, 0));
   CHECK_ERROR (!r, conn, "virDomainGetXMLDesc");
 
   rv = caml_copy_string (r);
@@ -989,7 +1003,7 @@ ocaml_libvirt_domain_get_scheduler_type (value domv)
   int nparams;
 
   WEAK_SYMBOL_CHECK (virDomainGetSchedulerType);
-  r = virDomainGetSchedulerType (dom, &nparams);
+  NONBLOCKING (r = virDomainGetSchedulerType (dom, &nparams));
   CHECK_ERROR (!r, conn, "virDomainGetSchedulerType");
 
   rv = caml_alloc_tuple (2);
@@ -998,7 +1012,7 @@ ocaml_libvirt_domain_get_scheduler_type (value domv)
   Store_field (rv, 1, nparams);
   CAMLreturn (rv);
 #else
-  NOT_SUPPORTED ("virDomainGetSchedulerType");
+  not_supported ("virDomainGetSchedulerType");
 #endif
 }
 
@@ -1015,7 +1029,7 @@ ocaml_libvirt_domain_get_scheduler_parameters (value domv, value nparamsv)
   int r, i;
 
   WEAK_SYMBOL_CHECK (virDomainGetSchedulerParameters);
-  r = virDomainGetSchedulerParameters (dom, params, &nparams);
+  NONBLOCKING (r = virDomainGetSchedulerParameters (dom, params, &nparams));
   CHECK_ERROR (r == -1, conn, "virDomainGetSchedulerParameters");
 
   rv = caml_alloc (nparams, 0);
@@ -1054,7 +1068,7 @@ ocaml_libvirt_domain_get_scheduler_parameters (value domv, value nparamsv)
   }
   CAMLreturn (rv);
 #else
-  NOT_SUPPORTED ("virDomainGetSchedulerParameters");
+  not_supported ("virDomainGetSchedulerParameters");
 #endif
 }
 
@@ -1108,12 +1122,12 @@ ocaml_libvirt_domain_set_scheduler_parameters (value domv, value paramsv)
   }
 
   WEAK_SYMBOL_CHECK (virDomainSetSchedulerParameters);
-  r = virDomainSetSchedulerParameters (dom, params, nparams);
+  NONBLOCKING (r = virDomainSetSchedulerParameters (dom, params, nparams));
   CHECK_ERROR (r == -1, conn, "virDomainSetSchedulerParameters");
 
   CAMLreturn (Val_unit);
 #else
-  NOT_SUPPORTED ("virDomainSetSchedulerParameters");
+  not_supported ("virDomainSetSchedulerParameters");
 #endif
 }
 
@@ -1126,7 +1140,7 @@ ocaml_libvirt_domain_define_xml (value connv, value xmlv)
   char *xml = String_val (xmlv);
   virDomainPtr r;
 
-  r = virDomainDefineXML (conn, xml);
+  NONBLOCKING (r = virDomainDefineXML (conn, xml));
   CHECK_ERROR (!r, conn, "virDomainDefineXML");
 
   rv = Val_domain (r, connv);
@@ -1141,7 +1155,7 @@ ocaml_libvirt_domain_undefine (value domv)
   virConnectPtr conn = Connect_domv (domv);
   int r;
 
-  r = virDomainUndefine (dom);
+  NONBLOCKING (r = virDomainUndefine (dom));
   CHECK_ERROR (r == -1, conn, "virDomainUndefine");
 
   CAMLreturn (Val_unit);
@@ -1155,7 +1169,7 @@ ocaml_libvirt_domain_create (value domv)
   virConnectPtr conn = Connect_domv (domv);
   int r;
 
-  r = virDomainCreate (dom);
+  NONBLOCKING (r = virDomainCreate (dom));
   CHECK_ERROR (r == -1, conn, "virDomainCreate");
 
   CAMLreturn (Val_unit);
@@ -1169,7 +1183,7 @@ ocaml_libvirt_domain_get_autostart (value domv)
   virConnectPtr conn = Connect_domv (domv);
   int r, autostart;
 
-  r = virDomainGetAutostart (dom, &autostart);
+  NONBLOCKING (r = virDomainGetAutostart (dom, &autostart));
   CHECK_ERROR (r == -1, conn, "virDomainGetAutostart");
 
   CAMLreturn (autostart ? Val_true : Val_false);
@@ -1183,7 +1197,7 @@ ocaml_libvirt_domain_set_autostart (value domv, value autostartv)
   virConnectPtr conn = Connect_domv (domv);
   int r, autostart = autostartv == Val_true ? 1 : 0;
 
-  r = virDomainSetAutostart (dom, autostart);
+  NONBLOCKING (r = virDomainSetAutostart (dom, autostart));
   CHECK_ERROR (r == -1, conn, "virDomainSetAutostart");
 
   CAMLreturn (Val_unit);
@@ -1197,7 +1211,7 @@ ocaml_libvirt_domain_set_vcpus (value domv, value nvcpusv)
   virConnectPtr conn = Connect_domv (domv);
   int r, nvcpus = Int_val (nvcpusv);
 
-  r = virDomainSetVcpus (dom, nvcpus);
+  NONBLOCKING (r = virDomainSetVcpus (dom, nvcpus));
   CHECK_ERROR (r == -1, conn, "virDomainSetVcpus");
 
   CAMLreturn (Val_unit);
@@ -1214,7 +1228,7 @@ ocaml_libvirt_domain_pin_vcpu (value domv, value vcpuv, value cpumapv)
   int vcpu = Int_val (vcpuv);
   int r;
 
-  r = virDomainPinVcpu (dom, vcpu, cpumap, maplen);
+  NONBLOCKING (r = virDomainPinVcpu (dom, vcpu, cpumap, maplen));
   CHECK_ERROR (r == -1, conn, "virDomainPinVcpu");
 
   CAMLreturn (Val_unit);
@@ -1236,7 +1250,7 @@ ocaml_libvirt_domain_get_vcpus (value domv, value maxinfov, value maplenv)
   memset (info, 0, sizeof (virVcpuInfo) * maxinfo);
   memset (cpumaps, 0, maxinfo * maplen);
 
-  r = virDomainGetVcpus (dom, info, maxinfo, cpumaps, maplen);
+  NONBLOCKING (r = virDomainGetVcpus (dom, info, maxinfo, cpumaps, maplen));
   CHECK_ERROR (r == -1, conn, "virDomainPinVcpu");
 
   /* Copy the virVcpuInfo structures. */
@@ -1270,7 +1284,7 @@ ocaml_libvirt_domain_get_max_vcpus (value domv)
   virConnectPtr conn = Connect_domv (domv);
   int r;
 
-  r = virDomainGetMaxVcpus (dom);
+  NONBLOCKING (r = virDomainGetMaxVcpus (dom));
   CHECK_ERROR (r == -1, conn, "virDomainGetMaxVcpus");
 
   CAMLreturn (Val_int (r));
@@ -1285,7 +1299,7 @@ ocaml_libvirt_domain_attach_device (value domv, value xmlv)
   char *xml = String_val (xmlv);
   int r;
 
-  r = virDomainAttachDevice (dom, xml);
+  NONBLOCKING (r = virDomainAttachDevice (dom, xml));
   CHECK_ERROR (r == -1, conn, "virDomainAttachDevice");
 
   CAMLreturn (Val_unit);
@@ -1300,7 +1314,7 @@ ocaml_libvirt_domain_detach_device (value domv, value xmlv)
   char *xml = String_val (xmlv);
   int r;
 
-  r = virDomainDetachDevice (dom, xml);
+  NONBLOCKING (r = virDomainDetachDevice (dom, xml));
   CHECK_ERROR (r == -1, conn, "virDomainDetachDevice");
 
   CAMLreturn (Val_unit);
@@ -1336,7 +1350,7 @@ ocaml_libvirt_domain_migrate_native (value domv, value dconnv, value flagsv, val
     bandwidth = Int_val (Field (optbandwidthv, 0));
 
   WEAK_SYMBOL_CHECK (virDomainMigrate);
-  r = virDomainMigrate (dom, dconn, flags, dname, uri, bandwidth);
+  NONBLOCKING (r = virDomainMigrate (dom, dconn, flags, dname, uri, bandwidth));
   CHECK_ERROR (!r, conn, "virDomainMigrate");
 
   rv = Val_domain (r, dconnv);
@@ -1344,7 +1358,7 @@ ocaml_libvirt_domain_migrate_native (value domv, value dconnv, value flagsv, val
   CAMLreturn (rv);
 
 #else /* virDomainMigrate not supported */
-  NOT_SUPPORTED ("virDomainMigrate");
+  not_supported ("virDomainMigrate");
 #endif
 }
 
@@ -1369,7 +1383,7 @@ ocaml_libvirt_domain_block_stats (value domv, value pathv)
   int r;
 
   WEAK_SYMBOL_CHECK (virDomainBlockStats);
-  r = virDomainBlockStats (dom, path, &stats, sizeof stats);
+  NONBLOCKING (r = virDomainBlockStats (dom, path, &stats, sizeof stats));
   CHECK_ERROR (r == -1, conn, "virDomainBlockStats");
 
   rv = caml_alloc (5, 0);
@@ -1381,7 +1395,7 @@ ocaml_libvirt_domain_block_stats (value domv, value pathv)
 
   CAMLreturn (rv);
 #else
-  NOT_SUPPORTED ("virDomainBlockStats");
+  not_supported ("virDomainBlockStats");
 #endif
 }
 
@@ -1398,7 +1412,7 @@ ocaml_libvirt_domain_interface_stats (value domv, value pathv)
   int r;
 
   WEAK_SYMBOL_CHECK (virDomainInterfaceStats);
-  r = virDomainInterfaceStats (dom, path, &stats, sizeof stats);
+  NONBLOCKING (r = virDomainInterfaceStats (dom, path, &stats, sizeof stats));
   CHECK_ERROR (r == -1, conn, "virDomainInterfaceStats");
 
   rv = caml_alloc (8, 0);
@@ -1413,7 +1427,7 @@ ocaml_libvirt_domain_interface_stats (value domv, value pathv)
 
   CAMLreturn (rv);
 #else
-  NOT_SUPPORTED ("virDomainInterfaceStats");
+  not_supported ("virDomainInterfaceStats");
 #endif
 }
 
@@ -1426,7 +1440,7 @@ ocaml_libvirt_network_lookup_by_name (value connv, value namev)
   char *name = String_val (namev);
   virNetworkPtr r;
 
-  r = virNetworkLookupByName (conn, name);
+  NONBLOCKING (r = virNetworkLookupByName (conn, name));
   CHECK_ERROR (!r, conn, "virNetworkLookupByName");
 
   rv = Val_network (r, connv);
@@ -1442,7 +1456,7 @@ ocaml_libvirt_network_lookup_by_uuid (value connv, value uuidv)
   char *uuid = String_val (uuidv);
   virNetworkPtr r;
 
-  r = virNetworkLookupByUUID (conn, (unsigned char *) uuid);
+  NONBLOCKING (r = virNetworkLookupByUUID (conn, (unsigned char *) uuid));
   CHECK_ERROR (!r, conn, "virNetworkLookupByUUID");
 
   rv = Val_network (r, connv);
@@ -1458,7 +1472,7 @@ ocaml_libvirt_network_lookup_by_uuid_string (value connv, value uuidv)
   char *uuid = String_val (uuidv);
   virNetworkPtr r;
 
-  r = virNetworkLookupByUUIDString (conn, uuid);
+  NONBLOCKING (r = virNetworkLookupByUUIDString (conn, uuid));
   CHECK_ERROR (!r, conn, "virNetworkLookupByUUIDString");
 
   rv = Val_network (r, connv);
@@ -1474,7 +1488,7 @@ ocaml_libvirt_network_create_xml (value connv, value xmlv)
   char *xml = String_val (xmlv);
   virNetworkPtr r;
 
-  r = virNetworkCreateXML (conn, xml);
+  NONBLOCKING (r = virNetworkCreateXML (conn, xml));
   CHECK_ERROR (!r, conn, "virNetworkCreateXML");
 
   rv = Val_network (r, connv);
@@ -1490,7 +1504,7 @@ ocaml_libvirt_network_define_xml (value connv, value xmlv)
   char *xml = String_val (xmlv);
   virNetworkPtr r;
 
-  r = virNetworkDefineXML (conn, xml);
+  NONBLOCKING (r = virNetworkDefineXML (conn, xml));
   CHECK_ERROR (!r, conn, "virNetworkDefineXML");
 
   rv = Val_network (r, connv);
@@ -1505,7 +1519,7 @@ ocaml_libvirt_network_undefine (value netv)
   virConnectPtr conn = Connect_netv (netv);
   int r;
 
-  r = virNetworkUndefine (net);
+  NONBLOCKING (r = virNetworkUndefine (net));
   CHECK_ERROR (r == -1, conn, "virNetworkUndefine");
 
   CAMLreturn (Val_unit);
@@ -1519,7 +1533,7 @@ ocaml_libvirt_network_create (value netv)
   virConnectPtr conn = Connect_netv (netv);
   int r;
 
-  r = virNetworkCreate (net);
+  NONBLOCKING (r = virNetworkCreate (net));
   CHECK_ERROR (r == -1, conn, "virNetworkCreate");
 
   CAMLreturn (Val_unit);
@@ -1533,7 +1547,7 @@ ocaml_libvirt_network_destroy (value netv)
   virConnectPtr conn = Connect_netv (netv);
   int r;
 
-  r = virNetworkDestroy (net);
+  NONBLOCKING (r = virNetworkDestroy (net));
   CHECK_ERROR (r == -1, conn, "virNetworkDestroy");
 
   /* So that we don't double-free in the finalizer: */
@@ -1550,7 +1564,7 @@ ocaml_libvirt_network_free (value netv)
   virConnectPtr conn = Connect_netv (netv);
   int r;
 
-  r = virNetworkFree (net);
+  NONBLOCKING (r = virNetworkFree (net));
   CHECK_ERROR (r == -1, conn, "virNetworkFree");
 
   /* So that we don't double-free in the finalizer: */
@@ -1568,7 +1582,7 @@ ocaml_libvirt_network_get_name (value netv)
   virConnectPtr conn = Connect_netv (netv);
   const char *r;
 
-  r = virNetworkGetName (net);
+  NONBLOCKING (r = virNetworkGetName (net));
   CHECK_ERROR (!r, conn, "virNetworkGetName");
 
   rv = caml_copy_string (r);
@@ -1585,7 +1599,7 @@ ocaml_libvirt_network_get_uuid (value netv)
   unsigned char uuid[VIR_UUID_BUFLEN];
   int r;
 
-  r = virNetworkGetUUID (net, uuid);
+  NONBLOCKING (r = virNetworkGetUUID (net, uuid));
   CHECK_ERROR (r == -1, conn, "virNetworkGetUUID");
 
   rv = caml_copy_string ((char *) uuid);
@@ -1602,7 +1616,7 @@ ocaml_libvirt_network_get_uuid_string (value netv)
   char uuid[VIR_UUID_STRING_BUFLEN];
   int r;
 
-  r = virNetworkGetUUIDString (net, uuid);
+  NONBLOCKING (r = virNetworkGetUUIDString (net, uuid));
   CHECK_ERROR (r == -1, conn, "virNetworkGetUUIDString");
 
   rv = caml_copy_string (uuid);
@@ -1618,7 +1632,7 @@ ocaml_libvirt_network_get_xml_desc (value netv)
   virConnectPtr conn = Connect_netv (netv);
   char *r;
 
-  r = virNetworkGetXMLDesc (net, 0);
+  NONBLOCKING (r = virNetworkGetXMLDesc (net, 0));
   CHECK_ERROR (!r, conn, "virNetworkGetXMLDesc");
 
   rv = caml_copy_string (r);
@@ -1635,7 +1649,7 @@ ocaml_libvirt_network_get_bridge_name (value netv)
   virConnectPtr conn = Connect_netv (netv);
   char *r;
 
-  r = virNetworkGetBridgeName (net);
+  NONBLOCKING (r = virNetworkGetBridgeName (net));
   CHECK_ERROR (!r, conn, "virNetworkGetBridgeName");
 
   rv = caml_copy_string (r);
@@ -1651,7 +1665,7 @@ ocaml_libvirt_network_get_autostart (value netv)
   virConnectPtr conn = Connect_netv (netv);
   int r, autostart;
 
-  r = virNetworkGetAutostart (net, &autostart);
+  NONBLOCKING (r = virNetworkGetAutostart (net, &autostart));
   CHECK_ERROR (r == -1, conn, "virNetworkGetAutostart");
 
   CAMLreturn (autostart ? Val_true : Val_false);
@@ -1665,7 +1679,7 @@ ocaml_libvirt_network_set_autostart (value netv, value autostartv)
   virConnectPtr conn = Connect_netv (netv);
   int r, autostart = autostartv == Val_true ? 1 : 0;
 
-  r = virNetworkSetAutostart (net, autostart);
+  NONBLOCKING (r = virNetworkSetAutostart (net, autostart));
   CHECK_ERROR (r == -1, conn, "virNetworkSetAutostart");
 
   CAMLreturn (Val_unit);
@@ -1768,7 +1782,7 @@ option_default (value option, value deflt)
 }
 #endif
 
-static value
+static void
 _raise_virterror (virConnectPtr conn, const char *fn)
 {
   CAMLparam0 ();
@@ -1792,7 +1806,21 @@ _raise_virterror (virConnectPtr conn, const char *fn)
   caml_raise_with_arg (*caml_named_value ("ocaml_libvirt_virterror"), rv);
 
   /*NOTREACHED*/
-  CAMLreturn (Val_unit);
+  CAMLreturn0;
+}
+
+/* Raise an error if a function is not supported. */
+static void
+not_supported (const char *fn)
+{
+  CAMLparam0 ();
+  CAMLlocal1 (fnv);
+
+  fnv = caml_copy_string (fn);
+  caml_raise_with_arg (*caml_named_value ("ocaml_libvirt_not_supported"), fnv);
+
+  /*NOTREACHED*/
+  CAMLreturn0;
 }
 
 /* Convert the virErrorNumber, virErrorDomain and virErrorLevel enums