我正在Django中调用我自己的Python C扩展,它负责一些长时间的计算。该扩展运行良好,甚至用户在C扩展进行计算时也可以浏览Django应用程序,因为我在扩展中实现了全局解释器锁(GIL)管理。但是,当另一个用户尝试执行扩展时(当它为初始用户运行时),Django崩溃(进程被终止),并且没有任何错误消息
在下面的代码中,您可以看到Django视图,它(通过请求POST)调用C扩展ftaCalculate
import ftaCalculate
from django.views.generic.base import TemplateView
# Computation
class ComputationView(TemplateView):
template_name = 'Generic/computation_page.html'
@staticmethod
def get_results(request):
if request.method == "POST": # When button is pressed
# Long computations
cs_min = ftaCalculate.mcs(N, tree)
else:
cs_min = None
return render(request, ComputationView.template_name, {'cs_min': cs_min})
当两个用户并行运行函数ftaCalculate.mcs
时,Django崩溃。我将在下文中介绍C代码的主要功能。函数comb
的内部是我使用Py_BEGIN_ALLOW_THREADS
和Py_END_ALLOW_THREADS
的地方
// Compute the Minimal cutsets
PyObject* Cmcs(int n, PyObject* tree)
{
// Initialize cs_all
cs_all = NULL;
// Get the leaves of the FTA (pointer)
PyObject *leaf_seq = PyObject_GetAttrString(tree, "leafs");
int n_comb = PyObject_Length(leaf_seq);
// All possible combinations of boolean values
int *indeces = (int *)malloc(n_comb * sizeof(int));
// Initialize mcs_index
ArrayInt num_mcs_index;
initArrayInt(&num_mcs_index, 1);
ArrayArray mcs_index;
initArrayArray(&mcs_index, 1, n_comb);
// String buffer for 0s/1s
int* str_buff = (int*) malloc(n_comb * sizeof(int));
int ind_str = 0;
// Get the combination
comb(n_comb, n, str_buff, ind_str, n_comb, 0, leaf_seq, indeces, &num_mcs_index, &mcs_index, tree);
free(str_buff);
str_buff=NULL;
free(indeces);
indeces=NULL;
// Order the cutsets
// Order the cutset by its count
HASH_SORT(cs_all, val_sort);
// Make array without redundant cutsets
PyObject *cs_all_sorted_readable = PyList_New(0);
struct my_struct *current_user, *tmp = NULL;
const char *cutset_name = NULL;
HASH_ITER(hh, cs_all, current_user, tmp) {
cutset_name = current_user->name;
PyObject *result_array= PyList_New(0);
for(int i = 0; cutset_name[i] != '\0'; i++) {
if(cutset_name[i] == '1'){
PyObject * str_int = PyObject_Str(PyList_GetItem(leaf_seq, i));
PyList_Append(result_array, str_int);
Py_XDECREF(str_int);
}
}
PyList_Append(cs_all_sorted_readable, result_array);
// Free allocated memory space
Py_CLEAR(result_array);
}
free(cutset_name);
cutset_name = NULL;
/*free(current_user);
free(tmp);*/
// Free allocated memory space
delete_all(cs_all); /* free any structures */
freeArrayInt(&num_mcs_index);
freeArrayArray(&mcs_index);
Py_CLEAR(leaf_seq);
return cs_all_sorted_readable;
}
// Our Python binding to our C function
// This will take one and only one non-keyword argument
static PyObject* mcs(PyObject* self, PyObject* args)
{
// instantiate the expected arguments
int n; // Order of cutset
PyObject *cb; // Tree object
// Parse the arguments
if(!PyArg_ParseTuple(args, "iO", &n, &cb))
return NULL;
// Determine whether the object has the expected structure
if (!PyObject_HasAttrString(cb, "pk")) {
PyErr_SetString(PyExc_TypeError, "mcs: the object structure is not the expected one");
return 0;
}
// Function to return the result back to Python
PyObject* result_cms = Cmcs(n, cb);
if(result_cms==NULL){
PyErr_SetString(PyExc_TypeError, "mcs: the returned object is null");
return NULL;
}
return result_cms;
}
// Our Module's Function Definition struct
// We require this `NULL` to signal the end of our method
// definition
static PyMethodDef myMethods[] = {
{ "mcs", mcs, METH_VARARGS | METH_KEYWORDS, "Computes Minimal Cutsets" },
{ NULL, NULL, 0, NULL }
};
// Our Module Definition struct
static struct PyModuleDef ftaCalculate = {
PyModuleDef_HEAD_INIT,
"ftaCalculate",
"Test Module",
-1,
myMethods
};
// Initializes our module using our above struct
PyMODINIT_FUNC PyInit_ftaCalculate(void)
{
return PyModule_Create(&ftaCalculate);
}
这种行为发生是正常的还是我遗漏了一些需要在C扩展中实现的东西
目前没有回答
相关问题 更多 >
编程相关推荐