From af5c2f941043cd439232ab976d602ba9c0508a46 Mon Sep 17 00:00:00 2001
From: James Arcus <jimbo@ucc.asn.au>
Date: Tue, 26 Mar 2019 14:33:57 +0800
Subject: [PATCH] VendServer - add writing traceback to file on SIGUSR1

---
 VendServer/TracebackPrinter.py | 30 ++++++++++++++++++++++++++++++
 VendServer/VendServer.py       |  6 ++++--
 bin/init.d/vendserver          |  3 ++-
 setup.py                       |  2 +-
 4 files changed, 37 insertions(+), 4 deletions(-)
 create mode 100644 VendServer/TracebackPrinter.py

diff --git a/VendServer/TracebackPrinter.py b/VendServer/TracebackPrinter.py
new file mode 100644
index 0000000..d89d695
--- /dev/null
+++ b/VendServer/TracebackPrinter.py
@@ -0,0 +1,30 @@
+"""
+TracebackPrinter.py - Prints the current stack trace to a specified
+file when SIGUSR1 is received.
+---
+Author: James Arcus <jimbo@ucc.asn.au>
+Based-On: python-traceback-signal
+          <https://github.com/angelcam/python-traceback-signal>
+Author: Angelcam <dev@angelcam.com>
+"""
+
+import os
+import sys
+import traceback
+import signal
+
+def print_traceback(wfd, frame):
+    msg = "Traceback signal received.\nTraceback (most recent call last):\n"
+    msg += ''.join(traceback.format_stack(frame))
+    os.write(wfd, msg)
+
+def register_sigusr(wfd):
+    def sigusr_handler(_, frame):
+        # first param is which signal
+        print_traceback(wfd, frame)
+
+    signal.signal(signal.SIGUSR1, sigusr_handler)
+
+def traceback_init(f):
+    wfd = os.open(f, os.O_WRONLY | os.O_APPEND | os.O_CREAT, 0o600)
+    register_sigusr(wfd)
diff --git a/VendServer/VendServer.py b/VendServer/VendServer.py
index c3cb3cb..f6ed8fe 100755
--- a/VendServer/VendServer.py
+++ b/VendServer/VendServer.py
@@ -20,6 +20,7 @@ from SnackConfig import get_snack#, get_snacks
 import socket
 from posix import geteuid
 from OpenDispense import OpenDispense as Dispense
+import TracebackPrinter
 
 CREDITS="""
 This vending machine software brought to you by:
@@ -963,6 +964,7 @@ def parse_args():
 	op.add_option('-v', '--verbose', dest='verbose', action='store_true', default=False, help='spit out lots of debug output')
 	op.add_option('-q', '--quiet', dest='quiet', action='store_true', default=False, help='only report errors')
 	op.add_option('--pid-file', dest='pid_file', metavar='FILE', default='', help='store daemon\'s pid in the given file')
+        op.add_option('--traceback-file', dest='traceback_file', default='', help='destination to print tracebacks when receiving SIGUSR1')
 	options, args = op.parse_args()
 
 	if len(args) != 0:
@@ -991,7 +993,7 @@ def set_stuff_up():
 	if options.daemon: become_daemon()
 	set_up_logging(options)
 	if options.pid_file != '': create_pid_file(options.pid_file)
-
+        if options.traceback_file != '': TracebackPrinter.traceback_init(options.traceback_file)
 	return options, config_opts
 
 def clean_up_nicely(options, config_opts):
@@ -1055,7 +1057,7 @@ def do_vend_server(options, config_opts):
 			continue
 		
 #		run_forever(rfh, wfh, options, config_opts)
-		
+
 		try:
 			vserver = VendServer()
 			vserver.run_forever(rfh, wfh, options, config_opts)
diff --git a/bin/init.d/vendserver b/bin/init.d/vendserver
index 6ae51ab..84b9dee 100755
--- a/bin/init.d/vendserver
+++ b/bin/init.d/vendserver
@@ -16,6 +16,7 @@ DESC="VendServer"
 NAME=vendserver
 DAEMON="/usr/local/uccvend-vendserver/vendserver"
 PIDFILE=/var/run/$NAME.pid
+TBFILE=/var/run/vendtraces.log
 SCRIPTNAME=/etc/init.d/$NAME
 DAEMON_ARGS=""
 
@@ -29,7 +30,7 @@ fi
 d_start() {
 	start-stop-daemon --start --pidfile $PIDFILE --nicelevel 5 \
 		--startas $DAEMON -- -d -sdaemon --pid-file=$PIDFILE \
-		$DAEMON_ARGS
+		--traceback-file=$TBFILE $DAEMON_ARGS
 }
 
 d_stop() {
diff --git a/setup.py b/setup.py
index 40de73a..f4e373f 100755
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@ test_requirements = [
 
 setup(
     name='uccvend-vendserver',
-    version='1.1',
+    version='1.1.1',
     description='UCC Snack Machine Server Code',
     long_description=readme + '\n\n' + history,
     author='ACC Murphy',
-- 
GitLab