source: deluge/core/daemon.py@ cd3221

2.0.x develop extjs4-port
Last change on this file since cd3221 was cd3221, checked in by Andrew Resch <andrewresch@gmail.com>, 15 years ago

Fix exceptions when gettext/locale cannot be initialized properly

  • Property mode set to 100644
File size: 7.7 KB
Line 
1#
2# daemon.py
3#
4# Copyright (C) 2007-2009 Andrew Resch <andrewresch@gmail.com>
5#
6# Deluge is free software.
7#
8# You may redistribute it and/or modify it under the terms of the
9# GNU General Public License, as published by the Free Software
10# Foundation; either version 3 of the License, or (at your option)
11# any later version.
12#
13# deluge is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16# See the GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with deluge. If not, write to:
20# The Free Software Foundation, Inc.,
21# 51 Franklin Street, Fifth Floor
22# Boston, MA 02110-1301, USA.
23#
24# In addition, as a special exception, the copyright holders give
25# permission to link the code of portions of this program with the OpenSSL
26# library.
27# You must obey the GNU General Public License in all respects for all of
28# the code used other than OpenSSL. If you modify file(s) with this
29# exception, you may extend this exception to your version of the file(s),
30# but you are not obligated to do so. If you do not wish to do so, delete
31# this exception statement from your version. If you delete this exception
32# statement from all source files in the program, then also delete it here.
33#
34
35import os
36import gettext
37import locale
38import pkg_resources
39from twisted.internet import reactor
40import twisted.internet.error
41
42import deluge.component as component
43import deluge.configmanager
44import deluge.common
45from deluge.core.rpcserver import RPCServer, export
46from deluge.log import LOG as log
47import deluge.error
48
49class Daemon(object):
50 def __init__(self, options=None, args=None, classic=False):
51 # Check for another running instance of the daemon
52 if os.path.isfile(deluge.configmanager.get_config_dir("deluged.pid")):
53 # Get the PID and the port of the supposedly running daemon
54 try:
55 (pid, port) = open(deluge.configmanager.get_config_dir("deluged.pid")).read().strip().split(";")
56 pid = int(pid)
57 port = int(port)
58 except ValueError:
59 pid = None
60 port = None
61
62
63 def process_running(pid):
64 if deluge.common.windows_check():
65 # Do some fancy WMI junk to see if the PID exists in Windows
66 from win32com.client import GetObject
67 def get_proclist():
68 WMI = GetObject('winmgmts:')
69 processes = WMI.InstancesOf('Win32_Process')
70 return [process.Properties_('ProcessID').Value for process in processes]
71 return pid in get_proclist()
72 else:
73 # We can just use os.kill on UNIX to test if the process is running
74 try:
75 os.kill(pid, 0)
76 except OSError:
77 return False
78 else:
79 return True
80
81 if pid is not None and process_running(pid):
82 # Ok, so a process is running with this PID, let's make doubly-sure
83 # it's a deluged process by trying to open a socket to it's port.
84 import socket
85 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
86 try:
87 s.connect(("127.0.0.1", port))
88 except socket.error:
89 # Can't connect, so it must not be a deluged process..
90 pass
91 else:
92 # This is a deluged!
93 s.close()
94 raise deluge.error.DaemonRunningError("There is a deluge daemon running with this config directory!")
95
96 # Initialize gettext
97 try:
98 locale.setlocale(locale.LC_ALL, '')
99 if hasattr(locale, "bindtextdomain"):
100 locale.bindtextdomain("deluge", pkg_resources.resource_filename("deluge", "i18n"))
101 if hasattr(locale, "textdomain"):
102 locale.textdomain("deluge")
103 gettext.bindtextdomain("deluge", pkg_resources.resource_filename("deluge", "i18n"))
104 gettext.textdomain("deluge")
105 gettext.install("deluge", pkg_resources.resource_filename("deluge", "i18n"))
106 except Exception, e:
107 log.error("Unable to initialize gettext/locale: %s", e)
108 import __builtin__
109 __builtin__.__dict__["_"] = lambda x: x
110
111 # Twisted catches signals to terminate, so just have it call the shutdown
112 # method.
113 reactor.addSystemEventTrigger("after", "shutdown", self.shutdown)
114
115 # Catch some Windows specific signals
116 if deluge.common.windows_check():
117 from win32api import SetConsoleCtrlHandler
118 from win32con import CTRL_CLOSE_EVENT
119 from win32con import CTRL_SHUTDOWN_EVENT
120 def win_handler(ctrl_type):
121 log.debug("ctrl_type: %s", ctrl_type)
122 if ctrl_type == CTRL_CLOSE_EVENT or ctrl_type == CTRL_SHUTDOWN_EVENT:
123 self.__shutdown()
124 return 1
125 SetConsoleCtrlHandler(win_handler)
126
127 version = deluge.common.get_version()
128
129 log.info("Deluge daemon %s", version)
130 log.debug("options: %s", options)
131 log.debug("args: %s", args)
132 # Set the config directory
133 if options and options.config:
134 deluge.configmanager.set_config_dir(options.config)
135
136 from deluge.core.core import Core
137 # Start the core as a thread and join it until it's done
138 self.core = Core()
139
140 port = self.core.config["daemon_port"]
141 if options and options.port:
142 port = options.port
143 if options and options.ui_interface:
144 interface = options.ui_interface
145 else:
146 interface = ""
147
148 self.rpcserver = RPCServer(
149 port=port,
150 allow_remote=self.core.config["allow_remote"],
151 listen=not classic,
152 interface=interface
153 )
154
155 # Register the daemon and the core RPCs
156 self.rpcserver.register_object(self.core)
157 self.rpcserver.register_object(self)
158
159
160 # Make sure we start the PreferencesManager first
161 component.start("PreferencesManager")
162
163 if not classic:
164 # Write out a pid file all the time, we use this to see if a deluged is running
165 # We also include the running port number to do an additional test
166 open(deluge.configmanager.get_config_dir("deluged.pid"), "wb").write(
167 "%s;%s\n" % (os.getpid(), port))
168
169 component.start()
170 try:
171 reactor.run()
172 finally:
173 self._shutdown()
174
175 @export()
176 def shutdown(self, *args, **kwargs):
177 reactor.callLater(0, reactor.stop)
178
179 def _shutdown(self, *args, **kwargs):
180 try:
181 os.remove(deluge.configmanager.get_config_dir("deluged.pid"))
182 except Exception, e:
183 log.exception(e)
184 log.error("Error removing deluged.pid!")
185
186 component.shutdown()
187 try:
188 reactor.stop()
189 except twisted.internet.error.ReactorNotRunning:
190 log.debug("Tried to stop the reactor but it is not running..")
191
192 @export()
193 def info(self):
194 """
195 Returns some info from the daemon.
196
197 :returns: str, the version number
198 """
199 return deluge.common.get_version()
200
201 @export()
202 def get_method_list(self):
203 """
204 Returns a list of the exported methods.
205 """
206 return self.rpcserver.get_method_list()
Note: See TracBrowser for help on using the repository browser.