(* libguestfs
- * Copyright (C) 2009-2010 Red Hat Inc.
+ * Copyright (C) 2009-2011 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
static PyObject *
py_guestfs_close (PyObject *self, PyObject *args)
{
+ PyThreadState *py_save = NULL;
PyObject *py_g;
guestfs_h *g;
return NULL;
g = get_handle (py_g);
+ if (PyEval_ThreadsInitialized ())
+ py_save = PyEval_SaveThread ();
guestfs_close (g);
+ if (PyEval_ThreadsInitialized ())
+ PyEval_RestoreThread (py_save);
Py_INCREF (Py_None);
return Py_None;
pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
pr "{\n";
+ pr " PyThreadState *py_save = NULL;\n";
pr " PyObject *py_g;\n";
pr " guestfs_h *g;\n";
pr " PyObject *py_r;\n";
pr " struct guestfs_%s_argv *optargs = &optargs_s;\n" name;
);
- let error_code =
- match ret with
- | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
- | RInt64 _ -> pr " int64_t r;\n"; "-1"
- | RConstString _ | RConstOptString _ ->
- pr " const char *r;\n"; "NULL"
- | RString _ -> pr " char *r;\n"; "NULL"
- | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
- | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
- | RStructList (_, typ) ->
- pr " struct guestfs_%s_list *r;\n" typ; "NULL"
- | RBufferOut _ ->
- pr " char *r;\n";
- pr " size_t size;\n";
- "NULL" in
+ (match ret with
+ | RErr | RInt _ | RBool _ -> pr " int r;\n"
+ | RInt64 _ -> pr " int64_t r;\n"
+ | RConstString _ | RConstOptString _ ->
+ pr " const char *r;\n"
+ | RString _ -> pr " char *r;\n"
+ | RStringList _ | RHashtable _ -> pr " char **r;\n"
+ | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
+ | RStructList (_, typ) ->
+ pr " struct guestfs_%s_list *r;\n" typ
+ | RBufferOut _ ->
+ pr " char *r;\n";
+ pr " size_t size;\n"
+ );
List.iter (
function
pr "\n"
);
+ (* Release Python GIL while running. This code is from
+ * libvirt/python/typewrappers.h. Thanks to Dan Berrange for
+ * showing us how to do this properly.
+ *)
+ pr " if (PyEval_ThreadsInitialized ())\n";
+ pr " py_save = PyEval_SaveThread ();\n";
+ pr "\n";
+
if optargs = [] then
pr " r = guestfs_%s " name
else
generate_c_call_args ~handle:"g" style;
pr ";\n";
+ pr "\n";
+ pr " if (PyEval_ThreadsInitialized ())\n";
+ pr " PyEval_RestoreThread (py_save);\n";
+ pr "\n";
+
List.iter (
function
| Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
pr " free (%s);\n" n
) args;
- pr " if (r == %s) {\n" error_code;
- pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
- pr " return NULL;\n";
- pr " }\n";
+ (match errcode_of_ret ret with
+ | `CannotReturnError -> ()
+ | `ErrorIsMinusOne ->
+ pr " if (r == -1) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
+ pr " return NULL;\n";
+ pr " }\n"
+ | `ErrorIsNULL ->
+ pr " if (r == NULL) {\n";
+ pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
+ pr " return NULL;\n";
+ pr " }\n"
+ );
pr "\n";
(match ret with
let doc = String.concat "\n " doc in
pr " u\"\"\"%s\"\"\"\n" doc;
);
+ (* Callers might pass in iterables instead of plain lists;
+ * convert those to plain lists because the C side of things
+ * cannot deal with iterables. (RHBZ#693306).
+ *)
+ List.iter (
+ function
+ | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
+ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
+ | BufferIn _ | Pointer _ -> ()
+ | StringList n | DeviceList n ->
+ pr " %s = list (%s)\n" n n
+ ) args;
pr " return libguestfsmod.%s (self._o" name;
List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (args@optargs);
pr ")\n\n";