X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/02b8771e8b60e68dc81e1ce39f3de6f8b9122b73..9fd2c54ef3bf35619766b304b3945695eb9271a6:/lib/base/console.cpp diff --git a/lib/base/console.cpp b/lib/base/console.cpp index db501945..add87066 100644 --- a/lib/base/console.cpp +++ b/lib/base/console.cpp @@ -55,8 +55,10 @@ int bidirpipe(int pfd[], const char *cmd , const char * const argv[], const char return(pid); } +DEFINE_REF(eConsoleAppContainer); + eConsoleAppContainer::eConsoleAppContainer() -:pid(-1), killstate(0), in(0), out(0), err(0) +:pid(-1), killstate(0) { for (int i=0; i < 3; ++i) { @@ -107,14 +109,18 @@ int eConsoleAppContainer::execute(const char *cmdline, const char * const argv[] // eDebug("pipe in = %d, out = %d, err = %d", fd[0], fd[1], fd[2]); + ::fcntl(fd[0], F_SETFL, O_NONBLOCK); ::fcntl(fd[1], F_SETFL, O_NONBLOCK); ::fcntl(fd[2], F_SETFL, O_NONBLOCK); - in = new eSocketNotifier(eApp, fd[0], eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Hungup ); - out = new eSocketNotifier(eApp, fd[1], eSocketNotifier::Write, false); - err = new eSocketNotifier(eApp, fd[2], eSocketNotifier::Read|eSocketNotifier::Priority ); + in = eSocketNotifier::create(eApp, fd[0], eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Hungup ); + out = eSocketNotifier::create(eApp, fd[1], eSocketNotifier::Write, false); + err = eSocketNotifier::create(eApp, fd[2], eSocketNotifier::Read|eSocketNotifier::Priority ); CONNECT(in->activated, eConsoleAppContainer::readyRead); CONNECT(out->activated, eConsoleAppContainer::readyWrite); CONNECT(err->activated, eConsoleAppContainer::readyErrRead); + in->m_clients.push_back(this); + out->m_clients.push_back(this); + err->m_clients.push_back(this); return 0; } @@ -143,10 +149,9 @@ void eConsoleAppContainer::kill() outbuf.pop(); delete [] d.data; } - delete in; - delete out; - delete err; - in=out=err=0; + in = 0; + out = 0; + err = 0; for (int i=0; i < 3; ++i) { @@ -209,6 +214,7 @@ void eConsoleAppContainer::closePipes() outbuf.pop(); delete [] d.data; } + in = 0; out = 0; err = 0; pid = -1; } @@ -333,152 +339,6 @@ struct eConsolePy PyObject *in_weakreflist; /* List of weak references */ }; -#define COMPATIBILITY_MODE -// with COMPATIBILITY_MODE enabled the callback list is accessed via console.appClosed.get() -// we remove this code after next enigma2 release... then the list should be accessed via console.appClosed ( without .get() ) - -#ifdef COMPATIBILITY_MODE -struct eListCompatibilityWrapper -{ - PyObject_HEAD - PyObject *list; - PyObject *in_weakreflist; /* List of weak references */ -}; - -static int -eListCompatibilityWrapper_traverse(eListCompatibilityWrapper *self, visitproc visit, void *arg) -{ - Py_VISIT(self->list); - return 0; -} - -static int -eListCompatibilityWrapper_clear(eListCompatibilityWrapper *self) -{ - Py_CLEAR(self->list); - return 0; -} - -static void -eListCompatibilityWrapper_dealloc(eListCompatibilityWrapper* self) -{ - if (self->in_weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) self); - eListCompatibilityWrapper_clear(self); - Org_Py_DECREF(self->list); - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject * -eListCompatibilityWrapper_get(eListCompatibilityWrapper *self, void *closure) -{ - Org_Py_INCREF(self->list); - return self->list; -} - -static PyMethodDef eListCompatibilityWrapper_methods[] = { - {"get", (PyCFunction)eListCompatibilityWrapper_get, METH_NOARGS, - "returns the list" - }, - {NULL} /* Sentinel */ -}; - -static PyGetSetDef eListCompatibilityWrapper_getseters[] = { - {NULL} /* Sentinel */ -}; - -static PyTypeObject eListCompatibilityWrapperType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "eConsoleImpl.eListCompatibilityWrapper", /*tp_name*/ - sizeof(eListCompatibilityWrapper), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)eListCompatibilityWrapper_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/ - "eListCompatibilityWrapper objects", /* tp_doc */ - (traverseproc)eListCompatibilityWrapper_traverse, /* tp_traverse */ - (inquiry)eListCompatibilityWrapper_clear, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(eListCompatibilityWrapper, in_weakreflist), /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - eListCompatibilityWrapper_methods, /* tp_methods */ - 0, /* tp_members */ - eListCompatibilityWrapper_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - 0, /* tp_alloc */ - 0, /* tp_new */ -}; - -static PyObject * -eConsolePy_dataAvail(eConsolePy *self, void *closure) -{ - eListCompatibilityWrapper *wrapper = (eListCompatibilityWrapper *)eListCompatibilityWrapperType.tp_alloc(&eListCompatibilityWrapperType, 0); - Org_Py_INCREF((PyObject*)wrapper); - wrapper->list = self->cont->dataAvail.get(); - wrapper->in_weakreflist = NULL; - return (PyObject*)wrapper; -} - -static PyObject * -eConsolePy_stdoutAvail(eConsolePy *self, void *closure) -{ - eListCompatibilityWrapper *wrapper = (eListCompatibilityWrapper *)eListCompatibilityWrapperType.tp_alloc(&eListCompatibilityWrapperType, 0); - Org_Py_INCREF((PyObject*)wrapper); - wrapper->list = self->cont->stdoutAvail.get(); - wrapper->in_weakreflist = NULL; - return (PyObject*)wrapper; -} - -static PyObject * -eConsolePy_stderrAvail(eConsolePy *self, void *closure) -{ - eListCompatibilityWrapper *wrapper = (eListCompatibilityWrapper *)eListCompatibilityWrapperType.tp_alloc(&eListCompatibilityWrapperType, 0); - Org_Py_INCREF((PyObject*)wrapper); - wrapper->list = self->cont->stderrAvail.get(); - wrapper->in_weakreflist = NULL; - return (PyObject*)wrapper; -} - -static PyObject * -eConsolePy_dataSent(eConsolePy *self, void *closure) -{ - eListCompatibilityWrapper *wrapper = (eListCompatibilityWrapper *)eListCompatibilityWrapperType.tp_alloc(&eListCompatibilityWrapperType, 0); - Org_Py_INCREF((PyObject*)wrapper); - wrapper->list = self->cont->dataSent.get(); - wrapper->in_weakreflist = NULL; - return (PyObject*)wrapper; -} - -static PyObject * -eConsolePy_appClosed(eConsolePy *self, void *closure) -{ - eListCompatibilityWrapper *wrapper = (eListCompatibilityWrapper *)eListCompatibilityWrapperType.tp_alloc(&eListCompatibilityWrapperType, 0); - Org_Py_INCREF((PyObject*)wrapper); - wrapper->list = self->cont->appClosed.get(); - wrapper->in_weakreflist = NULL; - return (PyObject*)wrapper; -} -#else static PyObject * eConsolePy_dataAvail(eConsolePy *self, void *closure) { @@ -508,7 +368,6 @@ eConsolePy_appClosed(eConsolePy *self, void *closure) { return self->cont->appClosed.get(); } -#endif static PyGetSetDef eConsolePy_getseters[] = { {"dataAvail", @@ -537,23 +396,23 @@ static PyGetSetDef eConsolePy_getseters[] = { static int eConsolePy_traverse(eConsolePy *self, visitproc visit, void *arg) { - PyObject *obj = self->cont->dataAvail.get(true); + PyObject *obj = self->cont->dataAvail.getSteal(); if (obj) { Py_VISIT(obj); } - obj = self->cont->stdoutAvail.get(true); + obj = self->cont->stdoutAvail.getSteal(); if (obj) { Py_VISIT(obj); } - obj = self->cont->stderrAvail.get(true); + obj = self->cont->stderrAvail.getSteal(); if (obj) { Py_VISIT(obj); } - obj = self->cont->dataSent.get(true); + obj = self->cont->dataSent.getSteal(); if (obj) { Py_VISIT(obj); } - obj = self->cont->appClosed.get(true); + obj = self->cont->appClosed.getSteal(); if (obj) { Py_VISIT(obj); } @@ -563,23 +422,23 @@ eConsolePy_traverse(eConsolePy *self, visitproc visit, void *arg) static int eConsolePy_clear(eConsolePy *self) { - PyObject *obj = self->cont->dataAvail.get(true); + PyObject *obj = self->cont->dataAvail.getSteal(true); if (obj) { Py_CLEAR(obj); } - obj = self->cont->stdoutAvail.get(true); + obj = self->cont->stdoutAvail.getSteal(true); if (obj) { Py_CLEAR(obj); } - obj = self->cont->stderrAvail.get(true); + obj = self->cont->stderrAvail.getSteal(true); if (obj) { Py_CLEAR(obj); } - obj = self->cont->dataSent.get(true); + obj = self->cont->dataSent.getSteal(true); if (obj) { Py_CLEAR(obj); } - obj = self->cont->appClosed.get(true); + obj = self->cont->appClosed.getSteal(true); if (obj) { Py_CLEAR(obj); } @@ -592,7 +451,7 @@ eConsolePy_dealloc(eConsolePy* self) if (self->in_weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); eConsolePy_clear(self); - delete self->cont; + self->cont->Release(); self->ob_type->tp_free((PyObject*)self); } @@ -601,6 +460,7 @@ eConsolePy_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { eConsolePy *self = (eConsolePy *)type->tp_alloc(type, 0); self->cont = new eConsoleAppContainer(); + self->cont->AddRef(); self->in_weakreflist = NULL; return (PyObject *)self; } @@ -617,34 +477,36 @@ eConsolePy_running(eConsolePy* self) static PyObject * eConsolePy_execute(eConsolePy* self, PyObject *argt) { - if (PyTuple_Size(argt) > 1) + Py_ssize_t argc = PyTuple_Size(argt); + if (argc > 1) { - PyObject *cmdline, *args; - PyArg_ParseTuple(argt, "OO", &cmdline, &args); - if (!PyString_Check(cmdline) || !PySequence_Check(args)) - return PyInt_FromLong(-2); - else + const char *argv[argc + 1]; + int argpos=0; + while(argpos < argc) { - PyObject *fast = PySequence_Fast(args, "2nd arg is not a sequence"); - Py_ssize_t size = PySequence_Fast_GET_SIZE(fast); - const char *argv[size + 1]; - int i=0; - for (; i < size; ++i) + PyObject *arg = PyTuple_GET_ITEM(argt, argpos); + if (!PyString_Check(arg)) { - PyObject *arg = PySequence_Fast_GET_ITEM(fast, i); /* borrowed ref */ - if (!PyString_Check(arg)) - return PyInt_FromLong(-3); - argv[i] = PyString_AsString(arg); /* borrowed pointer */ + char err[255]; + if (argpos) + snprintf(err, 255, "arg %d is not a string", argpos); + else + snprintf(err, 255, "cmd is not a string!"); + PyErr_SetString(PyExc_TypeError, err); + return NULL; } - argv[i] = 0; - return PyInt_FromLong(self->cont->execute(PyString_AsString(cmdline), argv)); /* borrowed pointer */ + argv[argpos++] = PyString_AsString(arg); } + argv[argpos] = 0; + return PyInt_FromLong(self->cont->execute(argv[0], argv+1)); } else { const char *str; if (PyArg_ParseTuple(argt, "s", &str)) return PyInt_FromLong(self->cont->execute(str)); + PyErr_SetString(PyExc_TypeError, + "cmd is not a string!"); } return NULL; } @@ -660,7 +522,11 @@ eConsolePy_write(eConsolePy* self, PyObject *args) { PyObject *ob; if (!PyArg_ParseTuple(args, "O", &ob) || !PyString_Check(ob)) + { + PyErr_SetString(PyExc_TypeError, + "1st arg must be a string, optionaly 2nd arg can be the string length"); return NULL; + } else { Py_ssize_t length; @@ -716,7 +582,11 @@ eConsolePy_dumpToFile(eConsolePy* self, PyObject *args) { char *filename; if (!PyArg_ParseTuple(args, "s", &filename)) + { + PyErr_SetString(PyExc_TypeError, + "arg must be a string (filename)"); return NULL; + } else { int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644); @@ -731,7 +601,11 @@ eConsolePy_readFromFile(eConsolePy* self, PyObject *args) { char *filename; if (!PyArg_ParseTuple(args, "s", &filename)) + { + PyErr_SetString(PyExc_TypeError, + "arg must be a string (filename)"); return NULL; + } else { int fd = open(filename, O_RDONLY); @@ -834,21 +708,12 @@ static PyMethodDef module_methods[] = { void eConsoleInit(void) { - PyObject* m; - - m = Py_InitModule3("eConsoleImpl", module_methods, + PyObject* m = Py_InitModule3("eConsoleImpl", module_methods, "Module that implements eConsoleAppContainer with working cyclic garbage collection."); if (m == NULL) return; -#ifdef COMPATIBILITY_MODE - if (!PyType_Ready(&eListCompatibilityWrapperType)) - { - Org_Py_INCREF((PyObject*)&eListCompatibilityWrapperType); - PyModule_AddObject(m, "eListCompatibilityWrapper", (PyObject*)&eListCompatibilityWrapperType); - } -#endif if (!PyType_Ready(&eConsolePyType)) { Org_Py_INCREF((PyObject*)&eConsolePyType);