#!/usr/bin/python
# Copyright 2010-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
#
# This is a helper which ebuild processes can use
# to communicate with portage's main python process.

import errno
import logging
import os
import pickle
import select
import signal
import sys
import time

def debug_signal(signum, frame):
	import pdb
	pdb.set_trace()
signal.signal(signal.SIGUSR1, debug_signal)

# Avoid sandbox violations after python upgrade.
pym_path = os.path.join(os.path.dirname(
	os.path.dirname(os.path.realpath(__file__))), "pym")
if os.environ.get("SANDBOX_ON") == "1":
	sandbox_write = os.environ.get("SANDBOX_WRITE", "").split(":")
	if pym_path not in sandbox_write:
		sandbox_write.append(pym_path)
		os.environ["SANDBOX_WRITE"] = \
			":".join(filter(None, sandbox_write))

import portage
portage._disable_legacy_globals()

class EbuildIpc(object):

	# Timeout for each individual communication attempt (we retry
	# as long as the daemon process appears to be alive).
	_COMMUNICATE_RETRY_TIMEOUT_SECONDS = 15
	_BUFSIZE = 4096

	def __init__(self):
		self.fifo_dir = os.environ['PORTAGE_BUILDDIR']
		self.ipc_in_fifo = os.path.join(self.fifo_dir, '.ipc_in')
		self.ipc_out_fifo = os.path.join(self.fifo_dir, '.ipc_out')
		self.ipc_lock_file = os.path.join(self.fifo_dir, '.ipc_lock')

	def _daemon_is_alive(self):
		try:
			builddir_lock = portage.locks.lockfile(self.fifo_dir,
				wantnewlockfile=True, flags=os.O_NONBLOCK)
		except portage.exception.TryAgain:
			return True
		else:
			portage.locks.unlockfile(builddir_lock)
			return False

	def communicate(self, args):

		# Make locks quiet since unintended locking messages displayed on
		# stdout could corrupt the intended output of this program.
		portage.locks._quiet = True
		lock_obj = portage.locks.lockfile(self.ipc_lock_file, unlinkfile=True)

		try:
			return self._communicate(args)
		finally:
			portage.locks.unlockfile(lock_obj)

	def _timeout_retry_msg(self, start_time, when):
		time_elapsed = time.time() - start_time
		portage.util.writemsg_level(
			portage.localization._(
			'ebuild-ipc timed out %s after %d seconds,' + \
			' retrying...\n') % (when, time_elapsed),
			level=logging.ERROR, noiselevel=-1)

	def _no_daemon_msg(self):
		portage.util.writemsg_level(
			portage.localization._(
			'ebuild-ipc: daemon process not detected\n'),
			level=logging.ERROR, noiselevel=-1)

	def _wait(self, pid, pr, msg):
		"""
		Wait on pid and return an appropriate exit code. This
		may return unsuccessfully due to timeout if the daemon
		process does not appear to be alive.
		"""

		start_time = time.time()

		while True:
			try:
				events = select.select([pr], [], [],
					self._COMMUNICATE_RETRY_TIMEOUT_SECONDS)
			except select.error as e:
				portage.util.writemsg_level(
					"ebuild-ipc: %s: %s\n" % \
					(portage.localization._('during select'), e),
					level=logging.ERROR, noiselevel=-1)
				continue

			if events[0]:
				break

			if self._daemon_is_alive():
				self._timeout_retry_msg(start_time, msg)
			else:
				self._no_daemon_msg()
				try:
					os.kill(pid, signal.SIGKILL)
					os.waitpid(pid, 0)
				except OSError as e:
					portage.util.writemsg_level(
						"ebuild-ipc: %s\n" % (e,),
						level=logging.ERROR, noiselevel=-1)
				return 2

		try:
			wait_retval = os.waitpid(pid, 0)
		except OSError as e:
			portage.util.writemsg_level(
				"ebuild-ipc: %s: %s\n" % (msg, e),
				level=logging.ERROR, noiselevel=-1)
			return 2

		if not os.WIFEXITED(wait_retval[1]):
			portage.util.writemsg_level(
				"ebuild-ipc: %s: %s\n" % (msg,
				portage.localization._('subprocess failure: %s') % \
				wait_retval[1]),
				level=logging.ERROR, noiselevel=-1)
			return 2

		return os.WEXITSTATUS(wait_retval[1])

	def _receive_reply(self, input_fd):

		# Timeouts are handled by the parent process, so just
		# block until input is available. For maximum portability,
		# use a single atomic read.
		buf = None
		while True:
			try:
				events = select.select([input_fd], [], [])
			except select.error as e:
				portage.util.writemsg_level(
					"ebuild-ipc: %s: %s\n" % \
					(portage.localization._('during select for read'), e),
					level=logging.ERROR, noiselevel=-1)
				continue

			if events[0]:
				# For maximum portability, use os.read() here since
				# array.fromfile() and file.read() are both known to
				# erroneously return an empty string from this
				# non-blocking fifo stream on FreeBSD (bug #337465).
				try:
					buf = os.read(input_fd, self._BUFSIZE)
				except OSError as e:
					if e.errno != errno.EAGAIN:
						portage.util.writemsg_level(
							"ebuild-ipc: %s: %s\n" % \
							(portage.localization._('read error'), e),
							level=logging.ERROR, noiselevel=-1)
						break
					# Assume that another event will be generated
					# if there's any relevant data.
					continue

				# Only one (atomic) read should be necessary.
				if buf:
					break

		retval = 2

		if not buf:

			portage.util.writemsg_level(
				"ebuild-ipc: %s\n" % \
				(portage.localization._('read failed'),),
				level=logging.ERROR, noiselevel=-1)

		else:

			try:
				reply = pickle.loads(buf)
			except SystemExit:
				raise
			except Exception as e:
				# The pickle module can raise practically
				# any exception when given corrupt data.
				portage.util.writemsg_level(
					"ebuild-ipc: %s\n" % (e,),
					level=logging.ERROR, noiselevel=-1)

			else:

				(out, err, retval) = reply

				if out:
					portage.util.writemsg_stdout(out, noiselevel=-1)

				if err:
					portage.util.writemsg(err, noiselevel=-1)

		return retval

	def _communicate(self, args):

		if not self._daemon_is_alive():
			self._no_daemon_msg()
			return 2

		# Open the input fifo before the output fifo, in order to make it
		# possible for the daemon to send a reply without blocking. This
		# improves performance, and also makes it possible for the daemon
		# to do a non-blocking write without a race condition.
		input_fd = os.open(self.ipc_out_fifo,
			os.O_RDONLY|os.O_NONBLOCK)

		# Use forks so that the child process can handle blocking IO
		# un-interrupted, while the parent handles all timeout
		# considerations. This helps to avoid possible race conditions
		# from interference between timeouts and blocking IO operations.
		pr, pw = os.pipe()
		pid = os.fork()

		if pid == 0:
			os.close(pr)

			# File streams are in unbuffered mode since we do atomic
			# read and write of whole pickles.
			output_file = open(self.ipc_in_fifo, 'wb', 0)
			output_file.write(pickle.dumps(args))
			output_file.close()
			os._exit(os.EX_OK)

		os.close(pw)

		msg = portage.localization._('during write')
		retval = self._wait(pid, pr, msg)
		os.close(pr)

		if retval != os.EX_OK:
			portage.util.writemsg_level(
				"ebuild-ipc: %s: %s\n" % (msg,
				portage.localization._('subprocess failure: %s') % \
				retval), level=logging.ERROR, noiselevel=-1)
			return retval

		if not self._daemon_is_alive():
			self._no_daemon_msg()
			return 2

		pr, pw = os.pipe()
		pid = os.fork()

		if pid == 0:
			os.close(pr)
			retval = self._receive_reply(input_fd)
			os._exit(retval)

		os.close(pw)
		retval = self._wait(pid, pr, portage.localization._('during read'))
		os.close(pr)
		os.close(input_fd)
		return retval

def ebuild_ipc_main(args):
	ebuild_ipc = EbuildIpc()
	return ebuild_ipc.communicate(args)

if __name__ == '__main__':
	sys.exit(ebuild_ipc_main(sys.argv[1:]))
