int main (int argc, char *argv[]) { guestfs_h *g; const char *key; void *data; size_t count; g = guestfs_create (); if (g == NULL) error (EXIT_FAILURE, errno, "guestfs_create"); if (guestfs_set_event_callback (g, close_callback, GUESTFS_EVENT_CLOSE, 0, NULL) == -1) exit (EXIT_FAILURE); guestfs_set_private (g, PREFIX "a", (void *) 1); guestfs_set_private (g, PREFIX "b", (void *) 2); guestfs_set_private (g, PREFIX "c", (void *) 3); guestfs_set_private (g, PREFIX "a", (void *) 4); /* overwrites previous */ /* Check we can fetch keys. */ assert (guestfs_get_private (g, PREFIX "a") == (void *) 4); assert (guestfs_get_private (g, PREFIX "b") == (void *) 2); assert (guestfs_get_private (g, PREFIX "c") == (void *) 3); assert (guestfs_get_private (g, PREFIX "d") == NULL); /* Check we can count keys by iterating. */ count = 0; data = guestfs_first_private (g, &key); while (data != NULL) { if (strncmp (key, PREFIX, strlen (PREFIX)) == 0) count++; data = guestfs_next_private (g, &key); } assert (count == 3); /* Delete some keys. */ guestfs_set_private (g, PREFIX "a", NULL); guestfs_set_private (g, PREFIX "b", NULL); /* Count them again. */ count = 0; data = guestfs_first_private (g, &key); while (data != NULL) { if (strncmp (key, PREFIX, strlen (PREFIX)) == 0) count++; data = guestfs_next_private (g, &key); } assert (count == 1); /* Closing should implicitly call the close_callback function. */ guestfs_close (g); assert (close_callback_called == 1); exit (EXIT_SUCCESS); }
/* Allocate handles and deal with finalization. */ static void guestfs_finalize (value gv) { guestfs_h *g = Guestfs_val (gv); if (g) { /* There is a nasty, difficult to solve case here where the * user deletes events in one of the callbacks that we are * about to invoke, resulting in a double-free. XXX */ size_t len, i; value **roots = get_all_event_callbacks (g, &len); value *v = guestfs_get_private (g, "_ocaml_g"); /* Close the handle: this could invoke callbacks from the list * above, which is why we don't want to delete them before * closing the handle. */ guestfs_close (g); /* Now unregister the global roots. */ for (i = 0; i < len; ++i) { caml_remove_global_root (roots[i]); free (roots[i]); } free (roots); caml_remove_global_root (v); free (v); } }
PyObject * py_guestfs_delete_event_callback (PyObject *self, PyObject *args) { PyObject *py_g; guestfs_h *g; int eh; PyObject *py_callback; char key[64]; if (!PyArg_ParseTuple (args, (char *) "Oi:guestfs_delete_event_callback", &py_g, &eh)) return NULL; g = get_handle (py_g); snprintf (key, sizeof key, "_python_event_%d", eh); py_callback = guestfs_get_private (g, key); if (py_callback) { Py_XDECREF (py_callback); guestfs_set_private (g, key, NULL); guestfs_delete_event_callback (g, eh); } Py_INCREF (Py_None); return Py_None; }
static void event_callback_wrapper_locked (guestfs_h *g, void *data, uint64_t event, int event_handle, int flags, const char *buf, size_t buf_len, const uint64_t *array, size_t array_len) { CAMLparam0 (); CAMLlocal5 (gv, evv, ehv, bufv, arrayv); CAMLlocal2 (rv, v); value *root; size_t i; root = guestfs_get_private (g, "_ocaml_g"); gv = *root; /* Only one bit should be set in 'event'. Which one? */ evv = Val_int (event_bitmask_to_event (event)); ehv = Val_int (event_handle); bufv = caml_alloc_string (buf_len); memcpy (String_val (bufv), buf, buf_len); arrayv = caml_alloc (array_len, 0); for (i = 0; i < array_len; ++i) { v = caml_copy_int64 (array[i]); Store_field (arrayv, i, v); } value args[5] = { gv, evv, ehv, bufv, arrayv }; rv = caml_callbackN_exn (*(value*)data, 5, args); /* Callbacks shouldn't throw exceptions. There's not much we can do * except to print it. */ if (Is_exception_result (rv)) fprintf (stderr, "libguestfs: uncaught OCaml exception in event callback: %s", caml_format_exception (Extract_exception (rv))); CAMLreturn0; }
JNIEXPORT void JNICALL Java_com_redhat_et_libguestfs_GuestFS__1delete_1event_1callback (JNIEnv *env, jobject obj, jlong jg, jint eh) { guestfs_h *g = (guestfs_h *) (long) jg; char key[64]; struct callback_data *data; snprintf (key, sizeof key, "_java_event_%d", eh); data = guestfs_get_private (g, key); if (data) { (*env)->DeleteGlobalRef (env, data->callback); free (data); guestfs_set_private (g, key, NULL); guestfs_delete_event_callback (g, eh); } }
/* Guestfs.delete_event_callback */ CAMLprim value ocaml_guestfs_delete_event_callback (value gv, value ehv) { CAMLparam2 (gv, ehv); char key[64]; int eh = Int_val (ehv); guestfs_h *g = Guestfs_val (gv); snprintf (key, sizeof key, "_ocaml_event_%d", eh); value *root = guestfs_get_private (g, key); if (root) { caml_remove_global_root (root); free (root); guestfs_set_private (g, key, NULL); guestfs_delete_event_callback (g, eh); } CAMLreturn (Val_unit); }