def _create_local_socket(self, init=0):
		"""Create local Unix-socket to listen commands instead of signals. If
		I{init} is set then close old socket"""

		if init and self.__local_sock:
			try:
				os.unlink(self.__local_sock.getsockname())
				self.__local_sock.shutdown(socket.SHUT_RDWR)
				logging.info('old local socket closed')
			except Exception as e:
				logging.warn('old local socket is already closed')

		try:
			os.unlink(self._config['server']['sock'])
		except:
			pass

		try:
			self.__local_sock = \
				socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
			# Non-blocking mode
			self.__local_sock.settimeout(0.0)
			self.__local_sock.bind(self._config['server']['sock'])
			self.__local_sock.listen(1)		# Max num of queued connections
		except Exception as e:
			logging.critical('cannot create local socket')
			logging.error(e)
			raise e

		logging.info('local socket created and binded on %s' % \
			self.__local_sock.getsockname())
	def main(self):
		"""Start main loop. From that moment the process will loop forever
		in this method"""

		logging.info('*' *50)
		logging.info('python %s' % sys.version.replace('\n', ''))
		logging.info('server started on %s:%s' % self.socket.getsockname())
		logging.info('SSL enabled' if self.cfg_ssl_enabled() else \
			'SSL disabled')
		logging.info('clients certificate ' + \
			('used' if self.cfg_certs_used() else 'not used'))
		logging.info(
			'local socket activated on %s' % self.__local_sock.getsockname())
		logging.info('pid (%d) written to %s' % (os.getpid(), self.pidfile))

		while 1:
			try:
				self.handle_request()
				# If we received shutdown request from local socket
				is_quit = self.handle_local_request()
				if is_quit:
					logging.info('stopping daemon')
					break
			except Exception as e:
				if self.__by_signal_do:
					self.__by_signal_do = 0
					continue
				from traceback import format_exception
				i = sys.exc_info()
				logging.error('\n'.join(format_exception(i[0], i[1], i[2])))
				del i
				break
	def finish_request(self, request, client_address):
		try:
			return ThreadingTCPServer.finish_request(self, request,
				client_address)
		except Exception as e:
			from traceback import format_exception
			i = sys.exc_info()
			logging.error('\n'.join(format_exception(i[0], i[1], i[2])).strip())
	def handle_local_request(self):
		"""Accept local socket connections"""

		c = None
		is_quit = 0
		try:
			# Are we have connection try?
			r, w, e = select.select([self.__local_sock.fileno()], [], [],
				self._config['server']['wait'])
			if not r:
				return
			c, addr, = self.__local_sock.accept()
			logging.info('local connection accepted')

			# Check if socket is ready for reading
			msg = b''
			r, w, e = select.select([c.fileno()], [], [], 0)
			if r:
				msg = c.recv(32, socket.MSG_DONTWAIT)
			else:
				logging.warn('socket not ready for reading')
				raise socket.error(100, 'socket not ready for reading')

			reply = b'unknown command'
			if msg == b'config':
				logging.info('request server configuration')
				reply = cpickle_dumps(self._config)
			elif msg == b'status':
				logging.info('request server status')
				reply = b'started'
			elif msg == b'shutdown':
				logging.info('request server shutdown')
				is_quit = 1
				reply = b'stopped'
			elif not msg:
				logging.info('no request')
			else:
				logging.info('unknown request')

			# Check if socket is ready for writing
			r, w, e = select.select([], [c.fileno()], [], 0)
			if w:
				c.send(reply, socket.MSG_DONTWAIT)
			else:
				logging.warn('socket not ready for writing')
				raise socket.error(101, 'socket not ready for writing')

		except Exception as e:
			logging.error(e)

		if c and not c._closed:
			c.close()
			logging.info('local connection closed')

		return is_quit
	def log_my_message(self, obj, msg_type='info'):
		"""Log message in format: <client_address> <message>"""

		if msg_type not in logging.LEVELS:
			logging.error('<log_my_message>: msg_type unknown')
			return
		c_addr = '%s:%s ' % self.client_address
		if hasattr(obj, '__str__') and isinstance(getattr(obj, '__str__'),
				collections.Callable):
			logging._log(msg_type, c_addr + str(obj))
		else:
			logging._log(msg_type, c_addr + repr(obj))
	def daemonize(self, parent1=None, parent2=None):
		"""
		Do the UNIX double-fork magic, see Stevens' I{"Advanced Programming in
		the UNIX Environment"} for details (B{ISBN 0201563177}) on
		U{http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16}.
		I{parent1}, I{parent2} - continue parent process with this functions.
		"""

		# Check for a pidfile to see if the daemon already runned
		if os.path.isfile(self.pidfile):
			msg_stdout('PID-file %s found! Remove it manually' % self.pidfile)
			return

		#logging.info('fork #1 process')
		try:
			pid = os.fork()
			if pid >0:
				if parent1:
					parent1(pid)
				# Exit first parent
				sys.exit()
		except OSError as e:
			logging.error('fork #1 failed: %d (%s)' % (e.errno, e.strerror))
			sys.exit(1)

		# Decouple from parent environment
		os.setsid()
		os.umask(0)

		# Do second fork
		#logging.info('fork #2 process')
		try:
			pid = os.fork()
			if pid >0:
				if parent2:
					parent2(pid)
				# Exit from second parent
				sys.exit()
		except OSError as e:
			logging.error('fork #2 failed: %d (%s)' % (e.errno, e.strerror))
			sys.exit(1)

		atexit.register(self.delpid)
		pid = str(os.getpid())
		open(self.pidfile,'w+').write('%s\n' % pid)
		logging.info('write PID (%s) to %s' % (pid, self.pidfile))

		return 1
	def handle_sigusr1(self, signum, frame):
		"""Handle signal SIGUSR1 to reload server configuration"""

		logging.info('reload server configuration (by signal)')
		# Catch exception in the I{main} method caused by received signal
		self.__by_signal_do = 1
		config = get_conf(CFG_PATH)

		# PID file cannot be changed
		config['server']['pid'] = self._config['server']['pid']

		# Log file path changed
		if self._config['server']['log'] != config['server']['log']:
			logging.close(0)
			logging.init(0, filename=config['server']['log'])

		# Local socket path changed
		init_loc = (config['server']['sock'] != self._config['server']['sock'])

		# SSL option changed and/or server ip/port, we need to
		# shutdown current socket and open new one
		init_srv = (config['ssl'] != self._config['ssl'] \
			or config['server']['port'] != self._config['server']['port'] \
			or config['server']['ip'] != self._config['server']['ip'])

		self._config = config.copy()

		if init_srv:
			try:
				self.socket.shutdown(socket.SHUT_RDWR)
				self._create_bind_activate(1)
			except Exception as e:
				# @todo: fix: if cannot bind new socket, do not reload config
				self.__by_signal_do = 0
				logging.error(e)

		if init_loc:
			try:
				self._create_local_socket(1)
			except Exception as e:
				pass

		self.socket.settimeout(config['server']['timeout'])
		# Non-blocking mode
		self.__local_sock.settimeout(0.0)
		logging.info('server configuration reloaded')
		del config
	def _create_bind_activate(self, init=0):
		"""Create socket, bind and activate server"""

		try:
			self._create_new_socket(init)
		except Exception as e:
			logging.critical('cannot create new socket')
			logging.error(e)
			raise e

		try:
			self.server_bind()
			self.server_activate()
		except Exception as e:
			logging.critical('cannot bind/activate server: %s' %e)
			raise e
		logging.info('server binded and activated on %s:%s' % \
			self.socket.getsockname())
	def _create_new_socket(self, init):
		"""Create new socket. I{init} >0 if need to replace internal server
		address used in the base class to create and bind socket"""

		if init:
			self.server_address = \
				(self._config['server']['ip'], self._config['server']['port'],)
			self.socket = socket.socket(self.address_family, self.socket_type)
			self.socket.settimeout(self._config['server']['timeout'])
			logging.info('network socket created')

		if self._config['ssl'].get('enable', 0) ==0:
			logging.info('SSL disabled')
			return

		logging.info('SSL enabled')
		try:
			logging.info('socket replaced by SSLSocket')
			import ssl
			if self._config['ssl'].get('verify_client', 0) ==0:
				logging.info('clients certificates not used')
				self.socket = ssl.SSLSocket(None,
					self._config['ssl']['pkey_file'],
					self._config['ssl']['cert_file'], True,
					ssl.CERT_NONE, ssl.PROTOCOL_SSLv3)
			else:
				logging.info('clients certificate required')
				self.socket = ssl.SSLSocket(None,
					self._config['ssl']['pkey_file'],
					self._config['ssl']['cert_file'], True,
					ssl.CERT_REQUIRED, ssl.PROTOCOL_SSLv3,
					self._config['ssl']['verify_loc'])
			self.socket.settimeout(self._config['server']['timeout'])
		except Exception as e:
			logging.error(e)
			raise RuntimeError('SSL error')