ambuild2/ipc/impl.py
author David Anderson <danderson@mozilla.com>
Wed Nov 13 16:23:04 2013 -0800 (2013-11-13)
changeset 184 b8e9518bd03b
parent 180 181f63116f44
permissions -rw-r--r--
Add Cygwin support.
     1 # vim: set ts=8 sts=2 sw=2 tw=99 et:
     2 #
     3 # This file is part of AMBuild.
     4 # 
     5 # AMBuild is free software: you can redistribute it and/or modify
     6 # it under the terms of the GNU General Public License as published by
     7 # the Free Software Foundation, either version 3 of the License, or
     8 # (at your option) any later version.
     9 # 
    10 # AMBuild is distributed in the hope that it will be useful,
    11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
    12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13 # GNU General Public License for more details.
    14 # 
    15 # You should have received a copy of the GNU General Public License
    16 # along with AMBuild. If not, see <http://www.gnu.org/licenses/>.
    17 import os, sys
    18 from . import process
    19 from ambuild2 import util
    20 
    21 if util.IsWindows() or util.IsCygwin():
    22   # Cygwin doesn't support SCM_RIGHTS (which, I guess, is actually unused)
    23   # but more importantly posix_spawn(), so we just cheat and use WinAPI 
    24   # directly, ignoring the sketchy Unix layer.
    25   from . import windows as ipc_impl
    26 elif util.IsLinux():
    27   from . import linux as ipc_impl
    28 elif util.IsBSD():
    29   from . import bsd as ipc_impl
    30 else:
    31   import select
    32   if hasattr(select, 'poll'):
    33     from . import generic_poll as ipc_impl
    34   else:
    35     raise Exception('Unknown platform: ' + util.Platform())
    36 
    37 ProcessManager = ipc_impl.ProcessManager
    38 MessagePump = ipc_impl.MessagePump
    39 
    40 if util.IsWindows() or util.IsCygwin():
    41   from . windows import NamedPipe as Channel
    42 else:
    43   from . posix_proc import SocketChannel as Channel
    44 
    45 class ChildWrapperListener(process.MessageListener):
    46   def __init__(self, mp, channel):
    47     super(ChildWrapperListener, self).__init__()
    48     self.mp = mp
    49     self.channel = channel
    50     self.listener = None
    51 
    52   def receiveMessage(self, channel, message):
    53     if message == process.Special.Close:
    54       self.listener.receiveClose(channel)
    55       return
    56 
    57     if message['id'] == '__start__':
    58       listener_type = message['listener_type']
    59       args = message['args']
    60       channels = ()
    61       if 'channels' in message:
    62         channels = message['channels']
    63       
    64       self.listener = listener_type(self.mp, self.channel, *(args + channels))
    65       return
    66 
    67     self.listener.receiveMessage(channel, message)
    68 
    69   def receiveError(self, channel, error):
    70     if self.listener:
    71       self.listener.receiveError(error)
    72     else:
    73       sys.stderr.write('[{0}] Parent process died, terminating...\n'.format(os.getpid()))
    74     sys.exit(1)
    75 
    76 def child_main(channel):
    77   mp = MessagePump()
    78   listener = ChildWrapperListener(mp, channel)
    79   mp.addChannel(channel, listener)
    80   try:
    81     mp.pump()
    82   except:
    83     sys.stdout.write('[{0}] Child process terminating abnormally.\n'.format(os.getpid()))
    84     raise
    85 #  sys.stdout.write('[{0}] Child process terminating normally.\n'.format(os.getpid()))