--- a/libupnpp/upnpplib.cxx
+++ b/libupnpp/upnpplib.cxx
@@ -108,6 +108,8 @@
return m->init_error;
}
+static const char* ccpDevNull = "/dev/null";
+
LibUPnP::LibUPnP(bool serveronly, string* hwaddr,
const string ifname, const string inip, unsigned short port)
{
@@ -144,6 +146,20 @@
if (ifname.empty())
strncpy(ip_address, inip.c_str(), ipalen);
+#if defined(HAVE_UPNPSETLOGLEVEL)
+ // We used to UpnpCloseLog() after UpnpInit(), but this can cause
+ // crashes because of the awful way upnpdebug.c is programmed, so
+ // no more. We do have to do something though because
+ // UpnpInitLog() creates the current filenames. The initial file
+ // names are IUpnpErrFile.txt and IUpnpInfoFile.txt, and they will
+ // be created in the current directory if debug is enabled and we
+ // do nothing. UpnpInitlog() is called by upnpapi.c:
+ // UpnpInit()->UpnpInitPreamble()->UpnpInitLog() So, set safe file
+ // names before calling UpnpInit() (needs to be static, the lib
+ // keeps a pointer to it).
+ UpnpSetLogFileNames(ccpDevNull, ccpDevNull);
+#endif
+
m->init_error = UpnpInit(ip_address[0] ? ip_address : 0, port);
if (m->init_error != UPNP_E_SUCCESS) {
@@ -154,10 +170,6 @@
LOGDEB("LibUPnP: Using IP " << UpnpGetServerIpAddress() << " port " <<
UpnpGetServerPort() << endl);
-
-#if defined(HAVE_UPNPSETLOGLEVEL)
- UpnpCloseLog();
-#endif
// Client initialization is simple, just do it. Defer device
// initialization because it's more complicated.
@@ -208,13 +220,20 @@
bool LibUPnP::setLogFileName(const std::string& fn, LogLevel level)
{
+#if defined(HAVE_UPNPSETLOGLEVEL)
std::unique_lock<std::mutex> lock(m->mutex);
-#if defined(HAVE_UPNPSETLOGLEVEL)
if (fn.empty() || level == LogLevelNone) {
- UpnpCloseLog();
+ // Can't call UpnpCloseLog() ! This closes the FILEs without
+ // any further precautions -> crashes
+ UpnpSetLogFileNames(ccpDevNull, ccpDevNull);
+ UpnpInitLog();
} else {
setLogLevel(level);
- UpnpSetLogFileNames(fn.c_str(), fn.c_str());
+ // the lib only keeps a pointer !
+ static string fnkeep(fn);
+ UpnpSetLogFileNames(fnkeep.c_str(), fnkeep.c_str());
+ // Because of the way upnpdebug.c is horribly coded, this
+ // loses 2 FILEs every time it's called.
int code = UpnpInitLog();
if (code != UPNP_E_SUCCESS) {
LOGERR(errAsString("UpnpInitLog", code) << endl);
@@ -232,6 +251,10 @@
#if defined(HAVE_UPNPSETLOGLEVEL)
switch (level) {
case LogLevelNone:
+ // This does not exist directly in pupnp, so log to
+ // /dev/null. SetLogFileName knows not to call us back in this
+ // case...
+ UpnpSetLogLevel(UPNP_CRITICAL);
setLogFileName("", LogLevelNone);
break;
case LogLevelError: