<p>Joshua C. Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/10832">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Joshua C. Colp: Looks good to me, but someone else must approve; Approved for Submit
  George Joseph: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">ast_coredumper:  Refactor the pid determination process<br><br>In order to get a dump of the running process, we need to find the<br>pid of the main asterisk process.  This can be tricky if there are<br>also instances of "asterisk -r" running or if an alternate location<br>for asterisk.conf was specified on the command line with the -C<br>option that also specified an alternation location for the pid file.<br><br>So now...<br><br>1. We find the asterisk executable with "which" or the --asterisk-bin<br>   command line option.<br>2. If there's only 1 process with an executable path that matches,<br>   we use that pid.  If not...<br>3. We try "<asterisk-bin> -rx 'core show settings'" and parse the<br>   output to find the pidfile, then read that for the pid.  If that<br>   didn't work...<br>4. We get a list of all the pids matching <asterisk-bin> and look<br>   in /proc/<pid>/cmdline for a -C argument and retry the "core show<br>   settings" using the same -C option.  We can't parse the output<br>   of "ps" to get the -C path because it may contain spaces.  The<br>   contents of /proc/<pid>/cmdline are delimited by NULLs.  For BSDs<br>   we may have to mount /proc first. :(<br><br>ASTERISK-28221<br>Reported by: Andrew Nagy<br><br>Change-Id: I8aa1f3f912f949df2b5348908803c636bde1d57c<br>---<br>M contrib/scripts/ast_coredumper<br>1 file changed, 84 insertions(+), 29 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/contrib/scripts/ast_coredumper b/contrib/scripts/ast_coredumper</span><br><span>index 0215edb..defb629 100755</span><br><span>--- a/contrib/scripts/ast_coredumper</span><br><span>+++ b/contrib/scripts/ast_coredumper</span><br><span>@@ -372,42 +372,97 @@</span><br><span> # Timestamp to use for output files</span><br><span> df=${tarball_uniqueid:-$(${DATEFORMAT})}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-if [ -z "$asterisk_bin" ]; then</span><br><span style="color: hsl(120, 100%, 40%);">+if [ x"$asterisk_bin" = x ]; then</span><br><span>     asterisk_bin=$(which asterisk)</span><br><span> fi</span><br><span> </span><br><span> if $running || $RUNNING ; then</span><br><span>   # We need to go through some gyrations to find the pid of the running</span><br><span>        # MAIN asterisk process and not someone or something running asterisk -r.</span><br><span style="color: hsl(0, 100%, 40%);">-       # The pid file may NOT be in /var/run/asterisk so we need to find any</span><br><span style="color: hsl(0, 100%, 40%);">-   # running asterisk process and see if -C was specified on the command</span><br><span style="color: hsl(0, 100%, 40%);">-   # line.  The chances of more than 1 asterisk instance running with</span><br><span style="color: hsl(0, 100%, 40%);">-      # different -C options is so unlikely that we're going to ignore it.</span><br><span style="color: hsl(0, 100%, 40%);">-        #</span><br><span style="color: hsl(0, 100%, 40%);">-       # 'ps axo command' should work on Linux (back to CentOS6) and FreeBSD.</span><br><span style="color: hsl(0, 100%, 40%);">-  # If asterisk was started with -C, get the asterisk.conf file.</span><br><span style="color: hsl(0, 100%, 40%);">-  # If it wasn't, assume /etc/asterisk/asterisk.conf</span><br><span style="color: hsl(0, 100%, 40%);">-  astetcconf=`ps axo command | sed -n -r -e "s/.*asterisk\s+.*-C\s+([^ ]+).*/\1/gp" | tail -1`</span><br><span style="color: hsl(0, 100%, 40%);">-  [ x$astetcconf = x ] && astetcconf=/etc/asterisk/asterisk.conf</span><br><span style="color: hsl(0, 100%, 40%);">-  # Now parse out astrundir and cat asterisk.pid</span><br><span style="color: hsl(0, 100%, 40%);">-  astrundir=$(sed -n -r -e "s/astrundir\s+[=>]+\s+(.*)/\1/gp" $astetcconf)</span><br><span style="color: hsl(0, 100%, 40%);">-   pid=$(cat $astrundir/asterisk.pid 2>/dev/null || : )</span><br><span style="color: hsl(0, 100%, 40%);">- if [ x$pid = x ] ; then</span><br><span style="color: hsl(0, 100%, 40%);">-         echo "Asterisk is not running"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    unset pid</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   # Simplest case first...</span><br><span style="color: hsl(120, 100%, 40%);">+      pids=$(pgrep -f "$asterisk_bin")</span><br><span style="color: hsl(120, 100%, 40%);">+    pidcount=$(echo $pids | wc -w)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if [ $pidcount -eq 0 ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+         >&2 echo "Asterisk is not running"</span><br><span style="color: hsl(120, 100%, 40%);">+           exit 1</span><br><span style="color: hsl(120, 100%, 40%);">+        fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # Single process, great.</span><br><span style="color: hsl(120, 100%, 40%);">+      if [ $pidcount -eq 1 ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+         pid=$pids</span><br><span style="color: hsl(120, 100%, 40%);">+             echo "Found a single asterisk instance running as process $pid"</span><br><span style="color: hsl(120, 100%, 40%);">+     fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # More than 1 asterisk process running</span><br><span style="color: hsl(120, 100%, 40%);">+        if [ x"$pid" = x ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+           # More than 1 process running, let's try asking asterisk for it's</span><br><span style="color: hsl(120, 100%, 40%);">+             # pidfile</span><br><span style="color: hsl(120, 100%, 40%);">+             pidfile=$("$asterisk_bin" -rx "core show settings" 2>/dev/null | sed -n -r -e "s/^\s*pid file:\s+(.*)/\1/gpi")</span><br><span style="color: hsl(120, 100%, 40%);">+               # We found it</span><br><span style="color: hsl(120, 100%, 40%);">+         if [ x"$pidfile" != x -a -f "$pidfile" ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+                   pid=$(cat "$pidfile")</span><br><span style="color: hsl(120, 100%, 40%);">+                       echo "Found pidfile $pidfile with process $pid"</span><br><span style="color: hsl(120, 100%, 40%);">+             fi</span><br><span style="color: hsl(120, 100%, 40%);">+    fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  # It's possible that asterisk was started with the -C option which means the</span><br><span style="color: hsl(120, 100%, 40%);">+      # control socket and pidfile might not be where we expect.  We're going to</span><br><span style="color: hsl(120, 100%, 40%);">+        # have to parse the process arguments to see if -C was specified.</span><br><span style="color: hsl(120, 100%, 40%);">+     # The first process that has a -C argument determines which config</span><br><span style="color: hsl(120, 100%, 40%);">+    # file to use to find the pidfile of the main process.</span><br><span style="color: hsl(120, 100%, 40%);">+        # NOTE: The ps command doesn't quote command line arguments that it</span><br><span style="color: hsl(120, 100%, 40%);">+       # displays so we need to look in /proc/<pid>/cmdline.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if [ x"$pid" = x ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+           # BSDs might not mount /proc by default :(</span><br><span style="color: hsl(120, 100%, 40%);">+            mounted_proc=0</span><br><span style="color: hsl(120, 100%, 40%);">+                if uname -o | grep -qi "bsd" ; then</span><br><span style="color: hsl(120, 100%, 40%);">+                 if ! mount | grep -qi "/proc" ; then</span><br><span style="color: hsl(120, 100%, 40%);">+                                echo "Temporarily mounting /proc"</span><br><span style="color: hsl(120, 100%, 40%);">+                           mounted_proc=1</span><br><span style="color: hsl(120, 100%, 40%);">+                                mount -t procfs proc /proc</span><br><span style="color: hsl(120, 100%, 40%);">+                    fi</span><br><span style="color: hsl(120, 100%, 40%);">+            fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          for p in $pids ; do</span><br><span style="color: hsl(120, 100%, 40%);">+                   # Fields in cmdline are delimited by NULLs</span><br><span style="color: hsl(120, 100%, 40%);">+                    astetcconf=$(sed -n -r -e "s/.*\x00-C\x00([^\x00]+).*/\1/gp" /proc/$p/cmdline)</span><br><span style="color: hsl(120, 100%, 40%);">+                      if [ x"$astetcconf" != x ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+                           pidfile=$("$asterisk_bin" -C "$astetcconf" -rx "core show settings" 2>/dev/null | sed -n -r -e "s/^\s*pid file:\s+(.*)/\1/gpi")</span><br><span style="color: hsl(120, 100%, 40%);">+                            if [ x"$pidfile" != x -a -f "$pidfile" ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+                                   pid=$(cat "$pidfile")</span><br><span style="color: hsl(120, 100%, 40%);">+                                       echo "Found pidfile $pidfile the hard way with process $pid"</span><br><span style="color: hsl(120, 100%, 40%);">+                                        break</span><br><span style="color: hsl(120, 100%, 40%);">+                         fi</span><br><span style="color: hsl(120, 100%, 40%);">+                    fi</span><br><span style="color: hsl(120, 100%, 40%);">+            done</span><br><span style="color: hsl(120, 100%, 40%);">+          if [ $mounted_proc -eq 1 ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+                     echo "Unmounting /proc"</span><br><span style="color: hsl(120, 100%, 40%);">+                     umount /proc</span><br><span style="color: hsl(120, 100%, 40%);">+          fi</span><br><span style="color: hsl(120, 100%, 40%);">+    fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if [ x"$pid" = x ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+           >&2 echo "Can't determine pid of the running asterisk instance"</span><br><span style="color: hsl(120, 100%, 40%);">+          exit 1</span><br><span style="color: hsl(120, 100%, 40%);">+        fi</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if $RUNNING ; then</span><br><span style="color: hsl(120, 100%, 40%);">+            answer=Y</span><br><span>     else</span><br><span style="color: hsl(0, 100%, 40%);">-            if $RUNNING ; then</span><br><span style="color: hsl(0, 100%, 40%);">-                      answer=Y</span><br><span style="color: hsl(0, 100%, 40%);">-                else</span><br><span style="color: hsl(0, 100%, 40%);">-                    read -p "WARNING:  Taking a core dump of the running asterisk instance will suspend call processing while the dump is saved.  Do you wish to continue? (y/N) " answer</span><br><span style="color: hsl(0, 100%, 40%);">-         fi</span><br><span style="color: hsl(0, 100%, 40%);">-              if [[ "$answer" =~ ^[Yy] ]] ; then</span><br><span style="color: hsl(0, 100%, 40%);">-                    cf="${OUTPUTDIR:-/tmp}/core-asterisk-running-$df"</span><br><span style="color: hsl(0, 100%, 40%);">-                     echo "Dumping running asterisk process to $cf"</span><br><span style="color: hsl(0, 100%, 40%);">-                        ${GDB} ${asterisk_bin} -p $pid -q --batch --ex "gcore $cf" >/dev/null 2>&1</span><br><span style="color: hsl(0, 100%, 40%);">-                  COREDUMPS+=("$cf")</span><br><span style="color: hsl(0, 100%, 40%);">-            else</span><br><span style="color: hsl(0, 100%, 40%);">-                    echo "Skipping dump of running process"</span><br><span style="color: hsl(0, 100%, 40%);">-               fi</span><br><span style="color: hsl(120, 100%, 40%);">+            read -p "WARNING:  Taking a core dump of the running asterisk instance will suspend call processing while the dump is saved.  Do you wish to continue? (y/N) " answer</span><br><span style="color: hsl(120, 100%, 40%);">+       fi</span><br><span style="color: hsl(120, 100%, 40%);">+    if [[ "$answer" =~ ^[Yy] ]] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+          cf="${OUTPUTDIR:-/tmp}/core-asterisk-running-$df"</span><br><span style="color: hsl(120, 100%, 40%);">+           echo "Dumping running asterisk process to $cf"</span><br><span style="color: hsl(120, 100%, 40%);">+              ${GDB} ${asterisk_bin} -p $pid -q --batch --ex "gcore $cf" >/dev/null 2>&1</span><br><span style="color: hsl(120, 100%, 40%);">+                COREDUMPS+=("$cf")</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+          echo "Skipping dump of running process"</span><br><span>    fi</span><br><span> fi</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10832">change 10832</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/10832"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I8aa1f3f912f949df2b5348908803c636bde1d57c </div>
<div style="display:none"> Gerrit-Change-Number: 10832 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation (1000185) </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua C. Colp <jcolp@digium.com> </div>