MythTV master
mythbackend.cpp
Go to the documentation of this file.
1#include "libmythbase/mythconfig.h"
2#if CONFIG_SYSTEMD_NOTIFY
3 #include <systemd/sd-daemon.h>
4#endif
5
6#include <csignal> // for signal
7#include <cstdlib>
8#include <thread>
9
10#include <QtGlobal>
11#if QT_VERSION >= QT_VERSION_CHECK(6,5,0)
12#include <QtEnvironmentVariables>
13#include <QtSystemDetection>
14#endif
15#ifndef Q_OS_WINDOWS
16#include <QCoreApplication>
17#else
18#include <QApplication>
19#endif
20
21#include <QDir>
22#include <QFile>
23#include <QFileInfo>
24#include <QMap>
25#ifdef Q_OS_DARWIN
26#include <QProcessEnvironment>
27#endif
28
29#include <unistd.h>
30
31// MythTV
32#include "libmyth/mythcontext.h"
33#include "libmythbase/compat.h"
38#include "libmythbase/mythdb.h"
43#include "libmythbase/mythversion.h"
45#include "libmythtv/dbcheck.h"
46#include "libmythtv/jobqueue.h"
50#include "libmythtv/tv_rec.h"
51
52// MythBackend
53#include "autoexpire.h"
54#include "backendcontext.h"
55#include "mainserver.h"
56#include "mediaserver.h"
59#include "scheduler.h"
60
61#include "servicesv2/v2myth.h"
62
63#define LOC QString("MythBackend: ")
64#define LOC_WARN QString("MythBackend, Warning: ")
65#define LOC_ERR QString("MythBackend, Error: ")
66
67#ifdef Q_OS_MACOS
68// 10.6 uses some file handles for its new Grand Central Dispatch thingy
69static constexpr long UNUSED_FILENO { 6 };
70#else
71static constexpr long UNUSED_FILENO { 3 };
72#endif
73
74int main(int argc, char **argv)
75{
77 if (!cmdline.Parse(argc, argv))
78 {
81 }
82
83 if (cmdline.toBool("showhelp"))
84 {
86 return GENERIC_EXIT_OK;
87 }
88
89 if (cmdline.toBool("showversion"))
90 {
92 return GENERIC_EXIT_OK;
93 }
94
95#ifndef Q_OS_WINDOWS
96#if HAVE_CLOSE_RANGE
97 close_range(UNUSED_FILENO, sysconf(_SC_OPEN_MAX) - 1, 0);
98#else
99 for (long i = UNUSED_FILENO; i < sysconf(_SC_OPEN_MAX) - 1; ++i)
100 close(i);
101#endif
102 QCoreApplication a(argc, argv);
103#else
104 // MINGW application needs a window to receive messages
105 // such as socket notifications :[
106 QApplication a(argc, argv);
107#endif
108 QCoreApplication::setApplicationName(MYTH_APPNAME_MYTHBACKEND);
109
110#ifdef Q_OS_DARWIN
111 QString path = QCoreApplication::applicationDirPath();
112 qputenv("PYTHONPATH",
113 QString("%1/../Resources/lib/%2:%1/../Resources/lib/%2/site-packages:%1/../Resources/lib/%2/lib-dynload:%3")
114 .arg(path)
115 .arg(QFileInfo(PYTHON_EXE).fileName())
116 .arg(QProcessEnvironment::systemEnvironment().value("PYTHONPATH"))
117 .toUtf8().constData());
118#endif
119
120 int retval = cmdline.Daemonize();
121 if (retval != GENERIC_EXIT_OK)
122 return retval;
123
124 bool daemonize = cmdline.toBool("daemon");
125 QString mask("general");
126 retval = cmdline.ConfigureLogging(mask, daemonize);
127 if (retval != GENERIC_EXIT_OK)
128 return retval;
129
130 if (daemonize)
131 // Don't listen to console input if daemonized
132 close(0);
133
134#if CONFIG_SYSTEMD_NOTIFY
135 (void)sd_notify(0, "STATUS=Connecting to database.");
136#endif
137
138 /*
139 InitializeMythDirs() is called by MythContext(), but we need to call it
140 first so XmlConfiguration() can find the configuration file.
141 */
143 // If setup has not been done (ie. the config.xml does not exist),
144 // set the ignoreDB flag, which will cause only the web-app to
145 // start, so that setup can be done.
146 bool ignoreDB = !(XmlConfiguration().FileExists());
147 if (ignoreDB)
149
150 // Init Parameters:
151 // bool Init(bool gui = true,
152 // bool promptForBackend = false,
153 // bool disableAutoDiscovery = false,
154 // bool ignoreDB = false);
155 MythContext context {MYTH_BINARY_VERSION};
156 if (!context.Init(false,false,false,ignoreDB))
157 {
158 LOG(VB_GENERAL, LOG_CRIT, "Failed to init MythContext.");
160 }
161 context.setCleanup(cleanup);
162
163 MythTranslation::load("mythfrontend");
164
165 setHttpProxy();
166
168
169 if (cmdline.toBool("setverbose") || cmdline.toBool("printsched") ||
170 cmdline.toBool("testsched") ||
171 cmdline.toBool("printexpire") || cmdline.toBool("setloglevel"))
172 {
174 return handle_command(cmdline);
175 }
176
178 retval = run_backend(cmdline);
179 // Retcode 258 is a special value to signal to mythbackend to restart
180 // This is used by the V2Myth/Shutdown?Restart=true API call
181 // Retcode 259 is a special value to signal to mythbackend to restart
182 // in webonly mode
183 if (retval == 258 || retval == 259)
184 {
185 char ** newargv = new char * [argc + 2];
186 std::string webonly = "--webonly";
187 newargv[0] = argv[0];
188 int newargc = 1;
189 for (int ix = 1 ; ix < argc ; ++ix)
190 {
191 if (webonly != argv[ix])
192 newargv[newargc++] = argv[ix];
193 }
194 if (retval == 259)
195 newargv[newargc++] = webonly.data();
196 newargv[newargc] = nullptr;
197 LOG(VB_GENERAL, LOG_INFO,
198 QString("Restarting mythbackend"));
199 std::this_thread::sleep_for(50ms);
200 int rc = execvp(newargv[0], newargv);
201 LOG(VB_GENERAL, LOG_ERR,
202 QString("execvp failed prog %1 rc=%2 errno=%3").arg(argv[0]).arg(rc).arg(errno));
203 delete[] newargv;
204 }
205 return retval;
206}
207
208/* vim: set expandtab tabstop=4 shiftwidth=4: */
bool toBool(const QString &key) const
Returns stored QVariant as a boolean.
virtual bool Parse(int argc, const char *const *argv)
Loop through argv and populate arguments with values.
void ApplySettingsOverride(void)
Apply all overrides to the global context.
int Daemonize(void) const
Fork application into background, and detatch from terminal.
int ConfigureLogging(const QString &mask="general", bool progress=false)
Read in logging options and initialize the logging interface.
static void PrintVersion(void)
Print application version information.
void PrintHelp(void) const
Print command line option help.
Startup context for MythTV.
Definition: mythcontext.h:20
void SetAsBackend(bool backend)
static void load(const QString &module_name)
Load a QTranslator for the user's preferred language.
static WebOnlyStartup s_WebOnlyStartup
Definition: v2myth.h:68
@ kWebOnlyDBSetup
Definition: v2myth.h:62
#define close
Definition: compat.h:28
@ GENERIC_EXIT_NO_MYTHCONTEXT
No MythContext available.
Definition: exitcodes.h:16
@ GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:13
@ GENERIC_EXIT_INVALID_CMDLINE
Command line parse error.
Definition: exitcodes.h:18
static constexpr const char * MYTH_APPNAME_MYTHBACKEND
Definition: mythappname.h:4
int main(int argc, char **argv)
Definition: mythbackend.cpp:74
static constexpr long UNUSED_FILENO
Definition: mythbackend.cpp:69
int handle_command(const MythBackendCommandLineParser &cmdline)
int run_backend(MythBackendCommandLineParser &cmdline)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void InitializeMythDirs(void)
Definition: mythdirs.cpp:35
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
void setHttpProxy(void)
Get network proxy settings from OS, and use for [Q]Http[Comms].
MythCommFlagCommandLineParser cmdline
static QString cleanup(const QString &str)