From d580351db41cef775a989a3c6b64e91114a16c33 Mon Sep 17 00:00:00 2001 From: David Wilson Date: Sun, 19 Aug 2018 23:04:40 +0100 Subject: [PATCH 1/4] Correct DISTROS variable name for ansible_tests. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1f8c5c6c..5dfdae00 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,4 +72,4 @@ matrix: # Sanity check against vanilla Ansible. One job suffices. - python: "2.7" - env: MODE=ansible VER=2.6.2 DISTRO=debian STRATEGY=linear + env: MODE=ansible VER=2.6.2 DISTROS=debian STRATEGY=linear From 50e285f7bac96f3d6b0868957b94fa5cf9680fb0 Mon Sep 17 00:00:00 2001 From: David Wilson Date: Sun, 19 Aug 2018 23:17:27 +0100 Subject: [PATCH 2/4] tests: update for identities_only change. --- .../integration/delegation/delegate_to_template.yml | 1 + .../ansible/integration/delegation/stack_construction.yml | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/tests/ansible/integration/delegation/delegate_to_template.yml b/tests/ansible/integration/delegation/delegate_to_template.yml index 8b1bd9af..b7dcc246 100644 --- a/tests/ansible/integration/delegation/delegate_to_template.yml +++ b/tests/ansible/integration/delegation/delegate_to_template.yml @@ -20,6 +20,7 @@ 'check_host_keys': 'ignore', 'connect_timeout': 10, 'hostname': 'cd-normal-alias', + 'identities_only': False, 'identity_file': None, 'password': None, 'port': None, diff --git a/tests/ansible/integration/delegation/stack_construction.yml b/tests/ansible/integration/delegation/stack_construction.yml index 8ab6e51b..f62b0e82 100644 --- a/tests/ansible/integration/delegation/stack_construction.yml +++ b/tests/ansible/integration/delegation/stack_construction.yml @@ -58,6 +58,7 @@ 'check_host_keys': 'ignore', 'connect_timeout': 10, 'hostname': 'alias-host', + 'identities_only': False, 'identity_file': None, 'password': None, 'port': None, @@ -91,6 +92,7 @@ 'check_host_keys': 'ignore', 'connect_timeout': 10, 'hostname': 'alias-host', + 'identities_only': False, 'identity_file': None, 'password': None, 'port': None, @@ -134,6 +136,7 @@ 'check_host_keys': 'ignore', 'connect_timeout': 10, 'hostname': 'cd-normal-normal', + 'identities_only': False, 'identity_file': None, 'password': None, 'port': None, @@ -167,6 +170,7 @@ 'check_host_keys': 'ignore', 'connect_timeout': 10, 'hostname': 'alias-host', + 'identities_only': False, 'identity_file': None, 'password': None, 'port': None, @@ -190,6 +194,7 @@ 'check_host_keys': 'ignore', 'connect_timeout': 10, 'hostname': 'cd-normal-alias', + 'identities_only': False, 'identity_file': None, 'password': None, 'port': None, @@ -233,6 +238,7 @@ 'check_host_keys': 'ignore', 'connect_timeout': 10, 'hostname': 'cd-newuser-normal-normal', + 'identities_only': False, 'identity_file': None, 'password': None, 'port': None, @@ -267,6 +273,7 @@ 'check_host_keys': 'ignore', 'connect_timeout': 10, 'hostname': 'alias-host', + 'identities_only': False, 'identity_file': None, 'password': None, 'port': None, From 4098d45dac605f3bdfe7cbf957c8a34f3b54eb53 Mon Sep 17 00:00:00 2001 From: David Wilson Date: Mon, 20 Aug 2018 00:21:34 +0100 Subject: [PATCH 3/4] tests: disable delegation tests on vanilla. --- .../delegation/delegate_to_template.yml | 3 ++ .../delegation/stack_construction.yml | 30 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/tests/ansible/integration/delegation/delegate_to_template.yml b/tests/ansible/integration/delegation/delegate_to_template.yml index b7dcc246..8c968640 100644 --- a/tests/ansible/integration/delegation/delegate_to_template.yml +++ b/tests/ansible/integration/delegation/delegate_to_template.yml @@ -8,6 +8,9 @@ gather_facts: no any_errors_fatal: true tasks: + - meta: end_play + when: not is_mitogen + - mitogen_get_stack: delegate_to: "{{ physical_host }}" register: out diff --git a/tests/ansible/integration/delegation/stack_construction.yml b/tests/ansible/integration/delegation/stack_construction.yml index f62b0e82..beb9a9d1 100644 --- a/tests/ansible/integration/delegation/stack_construction.yml +++ b/tests/ansible/integration/delegation/stack_construction.yml @@ -19,6 +19,9 @@ - name: integration/delegation/stack_construction.yml hosts: cd-normal tasks: + - meta: end_play + when: not is_mitogen + # used later for local_action test. - local_action: custom_python_detect_environment register: local_env @@ -27,6 +30,9 @@ - hosts: cd-normal any_errors_fatal: true tasks: + - meta: end_play + when: not is_mitogen + - mitogen_get_stack: register: out - assert: @@ -47,6 +53,9 @@ - hosts: cd-normal tasks: + - meta: end_play + when: not is_mitogen + - mitogen_get_stack: delegate_to: cd-alias register: out @@ -82,6 +91,9 @@ - hosts: cd-alias tasks: + - meta: end_play + when: not is_mitogen + - mitogen_get_stack: register: out - assert: @@ -116,6 +128,9 @@ - hosts: cd-normal-normal tasks: + - meta: end_play + when: not is_mitogen + - mitogen_get_stack: register: out - assert: @@ -160,6 +175,9 @@ - hosts: cd-normal-alias tasks: + - meta: end_play + when: not is_mitogen + - mitogen_get_stack: register: out - assert: @@ -218,6 +236,9 @@ - hosts: cd-newuser-normal-normal tasks: + - meta: end_play + when: not is_mitogen + - mitogen_get_stack: register: out - assert: @@ -262,6 +283,9 @@ - hosts: cd-newuser-normal-normal tasks: + - meta: end_play + when: not is_mitogen + - mitogen_get_stack: delegate_to: cd-alias register: out @@ -297,6 +321,9 @@ - hosts: cd-newuser-normal-normal tasks: + - meta: end_play + when: not is_mitogen + - local_action: mitogen_get_stack register: out - assert: @@ -315,6 +342,9 @@ - hosts: cd-newuser-doas-normal tasks: + - meta: end_play + when: not is_mitogen + - mitogen_get_stack: register: out - assert: From 49f3a61164f99722485a1e2393361e99214fcedc Mon Sep 17 00:00:00 2001 From: David Wilson Date: Mon, 20 Aug 2018 00:33:52 +0100 Subject: [PATCH 4/4] parent: prevent subprocess.Popen.__del__ from calling waitpid(). Closes #253. --- mitogen/parent.py | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/mitogen/parent.py b/mitogen/parent.py index 44504258..ca57efea 100644 --- a/mitogen/parent.py +++ b/mitogen/parent.py @@ -175,6 +175,30 @@ def create_socketpair(): return parentfp, childfp +def detach_popen(*args, **kwargs): + """ + Use :class:`subprocess.Popen` to construct a child process, then hack the + Popen so that it forgets the child it created, allowing it to survive a + call to Popen.__del__. + + If the child process is not detached, there is a race between it exitting + and __del__ being called. If it exits before __del__ runs, then __del__'s + call to :func:`os.waitpid` will capture the one and only exit event + delivered to this process, causing later 'legitimate' calls to fail with + ECHILD. + + :returns: + Process ID of the new child. + """ + # This allows Popen() to be used for e.g. graceful post-fork error + # handling, without tying the surrounding code into managing a Popen + # object, which isn't possible for at least :mod:`mitogen.fork`. This + # should be replaced by a swappable helper class in a future version. + proc = subprocess.Popen(*args, **kwargs) + proc._child_created = False + return proc.pid + + def create_child(args, merge_stdio=False, preexec_fn=None): """ Create a child process whose stdin/stdout is connected to a socket. @@ -201,7 +225,7 @@ def create_child(args, merge_stdio=False, preexec_fn=None): else: extra = {} - proc = subprocess.Popen( + pid = detach_popen( args=args, stdin=childfp, stdout=childfp, @@ -215,8 +239,8 @@ def create_child(args, merge_stdio=False, preexec_fn=None): parentfp.close() LOG.debug('create_child() child %d fd %d, parent %d, cmd: %s', - proc.pid, fd, os.getpid(), Argv(args)) - return proc.pid, fd, None + pid, fd, os.getpid(), Argv(args)) + return pid, fd, None def _acquire_controlling_tty(): @@ -250,7 +274,7 @@ def tty_create_child(args): disable_echo(master_fd) disable_echo(slave_fd) - proc = subprocess.Popen( + pid = detach_popen( args=args, stdin=slave_fd, stdout=slave_fd, @@ -261,8 +285,8 @@ def tty_create_child(args): os.close(slave_fd) LOG.debug('tty_create_child() child %d fd %d, parent %d, cmd: %s', - proc.pid, master_fd, os.getpid(), Argv(args)) - return proc.pid, master_fd, None + pid, master_fd, os.getpid(), Argv(args)) + return pid, master_fd, None def hybrid_tty_create_child(args): @@ -284,7 +308,7 @@ def hybrid_tty_create_child(args): mitogen.core.set_block(childfp) disable_echo(master_fd) disable_echo(slave_fd) - proc = subprocess.Popen( + pid = detach_popen( args=args, stdin=childfp, stdout=childfp, @@ -300,8 +324,8 @@ def hybrid_tty_create_child(args): parentfp.close() LOG.debug('hybrid_tty_create_child() pid=%d stdio=%d, tty=%d, cmd: %s', - proc.pid, stdio_fd, master_fd, Argv(args)) - return proc.pid, stdio_fd, master_fd + pid, stdio_fd, master_fd, Argv(args)) + return pid, stdio_fd, master_fd def write_all(fd, s, deadline=None):