From 3fff05bc28a9974c1d1022b6aaa1b07e89ecd036 Mon Sep 17 00:00:00 2001 From: dave Date: Wed, 16 Aug 2017 21:36:15 -0700 Subject: [PATCH] better subprocess handling --- pysonic/api.py | 50 ++++++++++++++++++++++++++++++++------------- pysonic/database.py | 4 ++-- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/pysonic/api.py b/pysonic/api.py index 0f38dfa..e55c7a2 100644 --- a/pysonic/api.py +++ b/pysonic/api.py @@ -4,6 +4,8 @@ import cherrypy import subprocess from time import time from random import shuffle +from threading import Thread +from time import sleep from bs4 import BeautifulSoup from pysonic.library import LETTER_GROUPS from pysonic.types import MUSIC_TYPES @@ -220,20 +222,40 @@ class PysonicApi(object): break yield data else: - def content(): - transcode_args = ["ffmpeg", "-i", fpath, "-map", "0:0", "-b:a", - "{}k".format(min(maxBitRate, self.options.max_bitrate)), - "-v", "0", "-f", "mp3", "-"] - logging.info(' '.join(transcode_args)) + transcode_args = ["ffmpeg", "-i", fpath, "-map", "0:0", "-b:a", + "{}k".format(min(maxBitRate, self.options.max_bitrate)), + "-v", "0", "-f", "mp3", "-"] + logging.info(' '.join(transcode_args)) + proc = subprocess.Popen(transcode_args, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + def content(proc): start = time() - proc = subprocess.Popen(transcode_args, stdout=subprocess.PIPE) - while True: - data = proc.stdout.read(16 * 1024) - if not data: - break - yield data - logging.warning("transcoded {} in {}s".format(id, int(time() - start))) - return content() + try: + while True: + data = proc.stdout.read(16 * 1024) + if not data: + break + yield data + finally: + proc.poll() + if proc.returncode is None: + logging.warning("transcoded {} in {}s".format(id, int(time() - start))) + else: + logging.error("transcode of {} exited with code {} after {}s".format(id, proc.returncode, + int(time() - start))) + + def stopit(proc): + try: + proc.wait(timeout=90) + except subprocess.TimeoutExpired: + logging.warning("killing timed-out transcoder") + proc.kill() + proc.wait() + + Thread(target=stopit, args=(proc, )).start() + + return content(proc) stream_view._cp_config = {'response.stream': True} @cherrypy.expose @@ -356,5 +378,5 @@ class PysonicApi(object): continue item_meta = item['metadata'] itemtype = "song" if item["type"] in MUSIC_TYPES else "album" - tag.append(self.render_node(doc, item, item_meta, {}, {}, tagname=itemtype)) + tag.append(self.render_node(doc, item, item_meta, {}, self.db.getnode(item["parent"])["metadata"], tagname=itemtype)) yield doc.prettify() diff --git a/pysonic/database.py b/pysonic/database.py index 508b7b0..b2f41a9 100644 --- a/pysonic/database.py +++ b/pysonic/database.py @@ -75,11 +75,11 @@ class PysonicDatabase(object): version = 1 if version < 2: logging.warning("migrating database to v2 from %s", version) - users_table = """CREATE TABLE 'stars' ( + stars_table = """CREATE TABLE 'stars' ( 'userid' INTEGER, 'nodeid' INTEGER, primary key ('userid', 'nodeid'))""" - cursor.execute(users_table) + cursor.execute(stars_table) version = 2 cursor.execute("""UPDATE meta SET value=? WHERE key="db_version";""", (str(version), ))