PyObject * py_guestfs_close (PyObject *self, PyObject *args) { PyThreadState *py_save = NULL; PyObject *py_g; guestfs_h *g; size_t i, len; PyObject **callbacks; if (!PyArg_ParseTuple (args, (char *) "O:guestfs_close", &py_g)) return NULL; g = get_handle (py_g); /* As in the OCaml bindings, there is a hard to solve case where the * caller can delete a callback from within the callback, resulting * in a double-free here. XXX */ callbacks = get_all_event_callbacks (g, &len); if (PyEval_ThreadsInitialized ()) py_save = PyEval_SaveThread (); guestfs_close (g); if (PyEval_ThreadsInitialized ()) PyEval_RestoreThread (py_save); for (i = 0; i < len; ++i) Py_XDECREF (callbacks[i]); free (callbacks); Py_INCREF (Py_None); return Py_None; }
/* 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); } }
JNIEXPORT void JNICALL Java_com_redhat_et_libguestfs_GuestFS__1close (JNIEnv *env, jobject obj, jlong jg) { guestfs_h *g = (guestfs_h *) (long) jg; size_t len; struct callback_data **data; /* 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 */ data = get_all_event_callbacks (env, g, &len); guestfs_close (g); if (len > 0) { size_t i; for (i = 0; i < len; ++i) { (*env)->DeleteGlobalRef (env, data[i]->callback); free (data[i]); } free (data); } }