<h5 dir="auto">ISSUE TYPE</h5>

<ul dir="auto">
<li>Bug Report</li>
</ul>
<h5 dir="auto">COMPONENT NAME</h5>
<p dir="auto">role inclusion</p>
<h5 dir="auto">ANSIBLE VERSION</h5>

<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="ansible 2.4.2.0
  config file = /home/user/.ansible.cfg
  configured module search path = [u'/home/user/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/user/ansible/lib/python2.7/site-packages/ansible
  executable location = /home/user/ansible/bin/ansible
  python version = 2.7.5 (default, Aug  2 2016, 04:20:16) [GCC 4.8.5 20150623 (Red Hat 4.8.5-4)]
"><pre class="notranslate"><code class="notranslate">ansible 2.4.2.0
  config file = /home/user/.ansible.cfg
  configured module search path = [u'/home/user/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /home/user/ansible/lib/python2.7/site-packages/ansible
  executable location = /home/user/ansible/bin/ansible
  python version = 2.7.5 (default, Aug  2 2016, 04:20:16) [GCC 4.8.5 20150623 (Red Hat 4.8.5-4)]

</code></pre></div>
<h5 dir="auto">CONFIGURATION</h5>
<p dir="auto">ANSIBLE_SSH_ARGS(/home/user/.ansible.cfg) = -o Protocol=2</p>
<h5 dir="auto">OS / ENVIRONMENT</h5>
<p dir="auto">Manager host is RHEL 7.3</p>
<h5 dir="auto">SUMMARY</h5>
<p dir="auto">Playbook has a list of roles to execute. If a role is repeated multiple times in the list, it is only executed the first time. If I use dict syntax to invoke the role, and add parameters to the role so that the duplicate invocations are slightly different, then the role gets executed as expected provided there are no exact duplicates in the role arguments.</p>
<h5 dir="auto">STEPS TO REPRODUCE</h5>
<ul dir="auto">
<li>Create a role that just prints some debug output.  Sample role below.</li>
<li>Invoke the role multiple times from a play</li>
<li>The role only executes once.</li>
<li>Edit the playbook to disambiguate the role invocations (see WORKAROUND below)</li>
<li>The role now executes once for each unique invocation</li>
</ul>
<p dir="auto">Sample role used in test:<br>
$ cat roles/do-nothing/tasks/main.yml</p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="---

- name: do nothing
  debug:
    var: ansible_version"><pre class="notranslate">---

- <span class="pl-ent">name</span>: <span class="pl-s">do nothing</span>
  <span class="pl-ent">debug</span>:
    <span class="pl-ent">var</span>: <span class="pl-s">ansible_version</span></pre></div>
<p dir="auto">Sample playbook used to reproduce:<br>
$ cat nothing1.yml</p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="---

 - hosts: &quot;{{ host_to_upgrade }}&quot;

   gather_facts: false

   roles:
     - do-nothing
     - do-nothing
     - do-nothing
"><pre class="notranslate">---

 - <span class="pl-ent">hosts</span>: <span class="pl-s"><span class="pl-pds">"</span>{{ host_to_upgrade }}<span class="pl-pds">"</span></span>

   <span class="pl-ent">gather_facts</span>: <span class="pl-c1">false</span>

   <span class="pl-ent">roles</span>:
     - <span class="pl-s">do-nothing</span>
     - <span class="pl-s">do-nothing</span>
     - <span class="pl-s">do-nothing</span>
</pre></div>
<h5 dir="auto">EXPECTED RESULTS</h5>
<p dir="auto">We should see the role "do-nothing" get run three times.</p>
<h5 dir="auto">ACTUAL RESULTS</h5>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ ansible-playbook -i ../hosts.test -e host_to_upgrade=njwdev1 nothing1.yml 

PLAY [njwdev1] *****************************************************************

TASK [do-nothing : do nothing] *************************************************
ok: [njwdev1] =&gt; {
    &quot;ansible_version&quot;: {
        &quot;full&quot;: &quot;2.4.2.0&quot;, 
        &quot;major&quot;: 2, 
        &quot;minor&quot;: 4, 
        &quot;revision&quot;: 2, 
        &quot;string&quot;: &quot;2.4.2.0&quot;
    }
}

PLAY RECAP *********************************************************************
njwdev1                    : ok=1    changed=0    unreachable=0    failed=0   "><pre class="notranslate"><code class="notranslate">$ ansible-playbook -i ../hosts.test -e host_to_upgrade=njwdev1 nothing1.yml 

PLAY [njwdev1] *****************************************************************

TASK [do-nothing : do nothing] *************************************************
ok: [njwdev1] =&gt; {
    "ansible_version": {
        "full": "2.4.2.0", 
        "major": 2, 
        "minor": 4, 
        "revision": 2, 
        "string": "2.4.2.0"
    }
}

PLAY RECAP *********************************************************************
njwdev1                    : ok=1    changed=0    unreachable=0    failed=0   
</code></pre></div>
<h4 dir="auto">WORKAROUND</h4>
<p dir="auto">This playbook shows how I'm working around the problem:</p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="---

 - hosts: &quot;{{ host_to_upgrade }}&quot;

   gather_facts: false

   roles:
     - do-nothing
     - { role: do-nothing, disambiguate_kludge: 1 }
     - { role: do-nothing, disambiguate_kludge: 2 }"><pre class="notranslate">---

 - <span class="pl-ent">hosts</span>: <span class="pl-s"><span class="pl-pds">"</span>{{ host_to_upgrade }}<span class="pl-pds">"</span></span>

   <span class="pl-ent">gather_facts</span>: <span class="pl-c1">false</span>

   <span class="pl-ent">roles</span>:
     - <span class="pl-s">do-nothing</span>
     - <span class="pl-s">{ role: do-nothing, disambiguate_kludge: 1 }</span>
     - <span class="pl-s">{ role: do-nothing, disambiguate_kludge: 2 }</span></pre></div>
<ul dir="auto">
<li>Note: If "disambiguate_kludge" is set to "1" instead of "2" in the 3rd role line above, then the role only executes twice.</li>
</ul>
<h5 dir="auto">Issue Type:</h5>
<p dir="auto">Bug Report</p>
<h5 dir="auto">Ansible Version:</h5>
<p dir="auto">$ ansible --version<br>
ansible 1.7.2</p>
<h5 dir="auto">Environment:</h5>
<p dir="auto">MacOS (also occurs on Ubuntu 14.04)</p>
<h5 dir="auto">Summary:</h5>
<p dir="auto">ssh logins that require sudo passwords can hang indefinitely.</p>
<h5 dir="auto">Steps To Reproduce:</h5>
<p dir="auto">I think the bug could be be reproduced if you enable sudo passwords and change sudo to a program that runs 'sleep 10' before it executes. Then run a playbook with the "--ask-sudo" parameter with that machine in the inventory.</p>
<p dir="auto">Here is what I think is happening:</p>
<ol dir="auto">
<li>Ansible attempts to ssh into a machine.</li>
<li>Ansible successfully logs in and attempts to run 'sudo'.</li>
<li>sudo takes a while and requires a password to be entered.</li>
<li>Ansible does a select() on the read socket.</li>
<li>The select() times out after 10 seconds. Ansible waits for the SSH process to terminate (from ansible/runner/connection_plugins/ssh.py):</li>
</ol>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="         if not rfd:
                    # timeout. wrap up process communication                                                                                                                                 
                    stdout = p.communicate()
                    raise errors.AnsibleError('ssh connection error waiting for sudo or su password prompt')"><pre class="notranslate"><code class="notranslate">         if not rfd:
                    # timeout. wrap up process communication                                                                                                                                 
                    stdout = p.communicate()
                    raise errors.AnsibleError('ssh connection error waiting for sudo or su password prompt')
</code></pre></div>
<p dir="auto">However, since Ansible is logged in and sudo is running, the process never terminates. communicate() gets stuck.</p>
<p dir="auto">Essentially, I think this is a corner case where the ssh login succeeds, but the time it takes for sudo to execute and ask for a password exceeds the timeout. Since the ssh session was successful, the ssh process will never return, causing Ansible to hang indefinitely.</p>
<p dir="auto">I verified this was happening by adding a 'continue', here:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="   if not rfd:
                    continue
                    # timeout. wrap up process communication                                                                                                                                 
                    stdout = p.communicate()"><pre class="notranslate"><code class="notranslate">   if not rfd:
                    continue
                    # timeout. wrap up process communication                                                                                                                                 
                    stdout = p.communicate()
</code></pre></div>
<p dir="auto">This worked--essentially a short time later, the select() returned successfully, and Ansible functioned well. To confirm this, I added some debug statements using time.time(). Here is what I saw:</p>
<ol dir="auto">
<li>t = 0: start of first select()</li>
<li>t = 10.000742: timeout occurs</li>
<li>t = 10.000874: second select() returns successfully</li>
</ol>
<p dir="auto">How to fix this? Ideally, we would have some way of knowing that the ssh session successfully logged in but was waiting for sudo. I don't think there is a foolproof way of knowing this.</p>
<p dir="auto">In any case, communicate() should have a timeout, so that if ssh fails to terminate, we either terminate the ssh process or run select() again just to be sure. There are some ideas here for how to implement a timeout:</p>
<p dir="auto"><a href="http://stackoverflow.com/questions/1191374/subprocess-with-timeout" rel="nofollow">http://stackoverflow.com/questions/1191374/subprocess-with-timeout</a></p>
<p dir="auto">For now, I've worked around the problem by changing timeout = 20, but I think the code still needs to prevent communicate() from getting stuck.</p>
<h5 dir="auto">Expected Results:</h5>
<p dir="auto">ssh logins and sudo executes fine</p>
<h5 dir="auto">Actual Results:</h5>
<p dir="auto">ssh process never returns and causes Ansible to get stuck</p>
<p dir="auto">I think a similar issue was reported in issue <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="37332391" data-permission-text="Title is private" data-url="https://github.com/ansible/ansible/issues/8058" data-hovercard-type="issue" data-hovercard-url="/ansible/ansible/issues/8058/hovercard" href="https://github.com/ansible/ansible/issues/8058">#8058</a>.</p>