diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index be2d7c1890..17ef7e8801 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -880,10 +880,10 @@ def detach_gui(): if os.fork() != 0: raise SystemExit(0) os.setsid() - si, so, se = os.open(os.devnull, os.O_RDONLY), os.open(os.devnull, os.O_WRONLY), os.open(os.devnull, os.O_WRONLY) - os.dup2(si, sys.__stdin__.fileno()) - os.dup2(so, sys.__stdout__.fileno()) - os.dup2(se, sys.__stderr__.fileno()) + try: + plugins['speedup'][0].detach(os.devnull) + except AttributeError: + pass # people running from source without updated binaries class Application(QApplication): diff --git a/src/calibre/library/server/main.py b/src/calibre/library/server/main.py index fd164cba40..f85584d5f8 100644 --- a/src/calibre/library/server/main.py +++ b/src/calibre/library/server/main.py @@ -10,7 +10,7 @@ from threading import Thread from calibre.library.server import server_config as config from calibre.library.server.base import LibraryServer -from calibre.constants import iswindows +from calibre.constants import iswindows, plugins import cherrypy def start_threaded_server(db, opts): @@ -67,7 +67,7 @@ The OPDS interface is advertised via BonJour automatically. ' work in all environments.')) return parser -def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): +def daemonize(): try: pid = os.fork() if pid > 0: @@ -93,12 +93,15 @@ def daemonize(stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): sys.exit(1) # Redirect standard file descriptors. - si = file(stdin, 'r') - so = file(stdout, 'a+') - se = file(stderr, 'a+', 0) - os.dup2(si.fileno(), sys.stdin.fileno()) - os.dup2(so.fileno(), sys.stdout.fileno()) - os.dup2(se.fileno(), sys.stderr.fileno()) + try: + plugins['speedup'][0].detach(os.devnull) + except AttributeError: # people running from source without updated binaries + si = os.open(os.devnull, os.O_RDONLY) + so = os.open(os.devnull, os.O_WRONLY) + se = os.open(os.devnull, os.O_WRONLY) + os.dup2(si, sys.stdin.fileno()) + os.dup2(so, sys.stdout.fileno()) + os.dup2(se, sys.stderr.fileno()) def main(args=sys.argv): diff --git a/src/calibre/utils/speedup.c b/src/calibre/utils/speedup.c index cf86298916..55158cc876 100644 --- a/src/calibre/utils/speedup.c +++ b/src/calibre/utils/speedup.c @@ -3,6 +3,7 @@ #include #include +#include #define min(x, y) ((x < y) ? x : y) #define max(x, y) ((x > y) ? x : y) @@ -97,6 +98,16 @@ speedup_pdf_float(PyObject *self, PyObject *args) { return ret; } +static PyObject* +speedup_detach(PyObject *self, PyObject *args) { + char *devnull = NULL; + if (!PyArg_ParseTuple(args, "s", &devnull)) return NULL; + if (freopen(devnull, "r", stdin) == NULL) return PyErr_SetFromErrno(PyExc_EnvironmentError); + if (freopen(devnull, "w", stdout) == NULL) return PyErr_SetFromErrno(PyExc_EnvironmentError); + if (freopen(devnull, "w", stderr) == NULL) return PyErr_SetFromErrno(PyExc_EnvironmentError); + Py_RETURN_NONE; +} + static PyMethodDef speedup_methods[] = { {"parse_date", speedup_parse_date, METH_VARARGS, "parse_date()\n\nParse ISO dates faster." @@ -106,6 +117,10 @@ static PyMethodDef speedup_methods[] = { "pdf_float()\n\nConvert float to a string representation suitable for PDF" }, + {"detach", speedup_detach, METH_VARARGS, + "detach()\n\nRedirect the standard I/O stream to the specified file (usually os.devnull)" + }, + {NULL, NULL, 0, NULL} };