2019-09-10 11:19:01 +02:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
2019-09-25 13:13:40 +02:00
|
|
|
/*
|
2012-10-31 17:19:38 +01:00
|
|
|
* Copyright (C) 2006 - 2012 Red Hat, Inc.
|
2008-11-03 04:13:42 +00:00
|
|
|
* Copyright (C) 2006 - 2008 Novell, Inc.
|
2006-02-27 04:31:52 +00:00
|
|
|
*/
|
|
|
|
|
|
2016-02-19 14:57:48 +01:00
|
|
|
#include "nm-default.h"
|
2011-03-14 01:00:56 -05:00
|
|
|
|
2018-10-12 17:07:25 +02:00
|
|
|
#include "nm-logging.h"
|
|
|
|
|
|
2009-08-21 12:16:17 -05:00
|
|
|
#include <dlfcn.h>
|
2006-02-27 04:31:52 +00:00
|
|
|
#include <syslog.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
#include <sys/stat.h>
|
2010-04-06 15:23:08 -07:00
|
|
|
#include <strings.h>
|
|
|
|
|
|
2015-07-08 16:21:21 +02:00
|
|
|
#if SYSTEMD_JOURNAL
|
|
|
|
|
#define SD_JOURNAL_SUPPRESS_LOCATION
|
|
|
|
|
#include <systemd/sd-journal.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-11-22 17:27:00 +01:00
|
|
|
#include "nm-glib-aux/nm-logging-base.h"
|
2019-04-15 08:16:00 +02:00
|
|
|
#include "nm-glib-aux/nm-time-utils.h"
|
2014-10-16 16:47:30 -04:00
|
|
|
#include "nm-errors.h"
|
2006-02-27 04:31:52 +00:00
|
|
|
|
2019-01-15 17:54:51 +01:00
|
|
|
/*****************************************************************************/
|
2013-06-14 14:51:04 -04:00
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
/* Notes about thread-safety:
|
|
|
|
|
*
|
|
|
|
|
* NetworkManager generally is single-threaded and uses a (GLib) mainloop.
|
|
|
|
|
* However, nm-logging is in parts thread-safe. That means:
|
|
|
|
|
*
|
|
|
|
|
* - functions that configure logging (nm_logging_init(), nm_logging_setup()) and
|
|
|
|
|
* most other functions MUST be called only from the main-thread. These functions
|
|
|
|
|
* are expected to be called infrequently, so they may or may not use a mutex
|
|
|
|
|
* (but the overhead is negligible here).
|
|
|
|
|
*
|
|
|
|
|
* - functions that do the actual logging logging (nm_log(), nm_logging_enabled()) are
|
|
|
|
|
* thread-safe and may be used from multiple threads.
|
|
|
|
|
* - When called from the not-main-thread, @mt_require_locking must be set to %TRUE.
|
|
|
|
|
* In this case, a Mutex will be used for accessing the global state.
|
|
|
|
|
* - When called from the main-thread, they may optionally pass @mt_require_locking %FALSE.
|
|
|
|
|
* This avoids extra locking and is in particular interesting for nm_logging_enabled(),
|
|
|
|
|
* which is expected to be called frequently and from the main-thread.
|
|
|
|
|
*
|
|
|
|
|
* Note that the logging macros honor %NM_THREAD_SAFE_ON_MAIN_THREAD define, to automatically
|
|
|
|
|
* set @mt_require_locking. That means, by default %NM_THREAD_SAFE_ON_MAIN_THREAD is "1",
|
|
|
|
|
* and code that only runs on the main-thread (which is the majority), can get away
|
|
|
|
|
* without locking.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2019-05-03 15:08:04 +02:00
|
|
|
G_STATIC_ASSERT (LOG_EMERG == 0);
|
|
|
|
|
G_STATIC_ASSERT (LOG_ALERT == 1);
|
|
|
|
|
G_STATIC_ASSERT (LOG_CRIT == 2);
|
|
|
|
|
G_STATIC_ASSERT (LOG_ERR == 3);
|
|
|
|
|
G_STATIC_ASSERT (LOG_WARNING == 4);
|
|
|
|
|
G_STATIC_ASSERT (LOG_NOTICE == 5);
|
|
|
|
|
G_STATIC_ASSERT (LOG_INFO == 6);
|
|
|
|
|
G_STATIC_ASSERT (LOG_DEBUG == 7);
|
|
|
|
|
|
2019-01-15 17:54:51 +01:00
|
|
|
/* We have more then 32 logging domains. Assert that it compiles to a 64 bit sized enum */
|
|
|
|
|
G_STATIC_ASSERT (sizeof (NMLogDomain) >= sizeof (guint64));
|
|
|
|
|
|
|
|
|
|
/* Combined domains */
|
|
|
|
|
#define LOGD_ALL_STRING "ALL"
|
|
|
|
|
#define LOGD_DEFAULT_STRING "DEFAULT"
|
|
|
|
|
#define LOGD_DHCP_STRING "DHCP"
|
|
|
|
|
#define LOGD_IP_STRING "IP"
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2010-04-06 15:23:08 -07:00
|
|
|
|
2019-01-15 17:49:52 +01:00
|
|
|
typedef enum {
|
|
|
|
|
LOG_BACKEND_GLIB,
|
|
|
|
|
LOG_BACKEND_SYSLOG,
|
|
|
|
|
LOG_BACKEND_JOURNAL,
|
|
|
|
|
} LogBackend;
|
|
|
|
|
|
2019-01-15 17:54:51 +01:00
|
|
|
typedef struct {
|
|
|
|
|
NMLogDomain num;
|
|
|
|
|
const char *name;
|
|
|
|
|
} LogDesc;
|
|
|
|
|
|
2019-01-15 18:35:25 +01:00
|
|
|
typedef struct {
|
|
|
|
|
char *logging_domains_to_string;
|
|
|
|
|
} GlobalMain;
|
|
|
|
|
|
2019-01-15 17:54:51 +01:00
|
|
|
typedef struct {
|
2015-10-07 11:07:09 +02:00
|
|
|
NMLogLevel log_level;
|
2016-05-23 12:02:31 +02:00
|
|
|
bool uses_syslog:1;
|
2019-01-16 16:16:49 +01:00
|
|
|
bool init_pre_done:1;
|
|
|
|
|
bool init_done:1;
|
2017-03-01 13:34:32 +01:00
|
|
|
bool debug_stderr:1;
|
2016-10-05 15:25:08 +02:00
|
|
|
const char *prefix;
|
2016-10-05 15:52:55 +02:00
|
|
|
const char *syslog_identifier;
|
2019-01-15 17:49:52 +01:00
|
|
|
|
|
|
|
|
/* before we setup syslog (during start), the backend defaults to GLIB, meaning:
|
|
|
|
|
* we use g_log() for all logging. At that point, the application is not yet supposed
|
|
|
|
|
* to do any logging and doing so indicates a bug.
|
|
|
|
|
*
|
|
|
|
|
* Afterwards, the backend is either SYSLOG or JOURNAL. From that point, also
|
|
|
|
|
* g_log() is redirected to this backend via a logging handler. */
|
|
|
|
|
LogBackend log_backend;
|
2019-01-15 17:54:51 +01:00
|
|
|
} Global;
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
G_LOCK_DEFINE_STATIC (log);
|
|
|
|
|
|
2019-01-15 18:35:25 +01:00
|
|
|
/* This data must only be accessed from the main-thread (and as
|
|
|
|
|
* such does not need any lock). */
|
|
|
|
|
static GlobalMain gl_main = { };
|
|
|
|
|
|
2019-01-15 14:27:37 +01:00
|
|
|
static union {
|
|
|
|
|
/* a union with an immutable and a mutable alias for the Global.
|
|
|
|
|
* Since nm-logging must be thread-safe, we must take care at which
|
2019-03-11 12:00:32 +01:00
|
|
|
* places we only read value ("imm") and where we modify them ("mut"). */
|
2019-01-15 14:27:37 +01:00
|
|
|
Global mut;
|
|
|
|
|
const Global imm;
|
|
|
|
|
} gl = {
|
|
|
|
|
.imm = {
|
|
|
|
|
/* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL); */
|
|
|
|
|
.log_level = LOGL_INFO,
|
|
|
|
|
.log_backend = LOG_BACKEND_GLIB,
|
|
|
|
|
.syslog_identifier = "SYSLOG_IDENTIFIER="G_LOG_DOMAIN,
|
|
|
|
|
.prefix = "",
|
|
|
|
|
},
|
2019-01-15 16:58:15 +01:00
|
|
|
};
|
|
|
|
|
|
2019-01-15 17:54:51 +01:00
|
|
|
NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL] = {
|
|
|
|
|
/* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL);
|
|
|
|
|
*
|
|
|
|
|
* Note: LOGD_VPN_PLUGIN is special and must be disabled for
|
|
|
|
|
* DEBUG and TRACE levels. */
|
|
|
|
|
[LOGL_INFO] = LOGD_DEFAULT,
|
|
|
|
|
[LOGL_WARN] = LOGD_DEFAULT,
|
|
|
|
|
[LOGL_ERR] = LOGD_DEFAULT,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2019-01-15 16:58:15 +01:00
|
|
|
static const LogDesc domain_desc[] = {
|
|
|
|
|
{ LOGD_PLATFORM, "PLATFORM" },
|
|
|
|
|
{ LOGD_RFKILL, "RFKILL" },
|
|
|
|
|
{ LOGD_ETHER, "ETHER" },
|
|
|
|
|
{ LOGD_WIFI, "WIFI" },
|
|
|
|
|
{ LOGD_BT, "BT" },
|
|
|
|
|
{ LOGD_MB, "MB" },
|
|
|
|
|
{ LOGD_DHCP4, "DHCP4" },
|
|
|
|
|
{ LOGD_DHCP6, "DHCP6" },
|
|
|
|
|
{ LOGD_PPP, "PPP" },
|
|
|
|
|
{ LOGD_WIFI_SCAN, "WIFI_SCAN" },
|
|
|
|
|
{ LOGD_IP4, "IP4" },
|
|
|
|
|
{ LOGD_IP6, "IP6" },
|
|
|
|
|
{ LOGD_AUTOIP4, "AUTOIP4" },
|
|
|
|
|
{ LOGD_DNS, "DNS" },
|
|
|
|
|
{ LOGD_VPN, "VPN" },
|
|
|
|
|
{ LOGD_SHARING, "SHARING" },
|
|
|
|
|
{ LOGD_SUPPLICANT,"SUPPLICANT" },
|
|
|
|
|
{ LOGD_AGENTS, "AGENTS" },
|
|
|
|
|
{ LOGD_SETTINGS, "SETTINGS" },
|
|
|
|
|
{ LOGD_SUSPEND, "SUSPEND" },
|
|
|
|
|
{ LOGD_CORE, "CORE" },
|
|
|
|
|
{ LOGD_DEVICE, "DEVICE" },
|
|
|
|
|
{ LOGD_OLPC, "OLPC" },
|
|
|
|
|
{ LOGD_INFINIBAND,"INFINIBAND" },
|
|
|
|
|
{ LOGD_FIREWALL, "FIREWALL" },
|
|
|
|
|
{ LOGD_ADSL, "ADSL" },
|
|
|
|
|
{ LOGD_BOND, "BOND" },
|
|
|
|
|
{ LOGD_VLAN, "VLAN" },
|
|
|
|
|
{ LOGD_BRIDGE, "BRIDGE" },
|
|
|
|
|
{ LOGD_DBUS_PROPS,"DBUS_PROPS" },
|
|
|
|
|
{ LOGD_TEAM, "TEAM" },
|
|
|
|
|
{ LOGD_CONCHECK, "CONCHECK" },
|
|
|
|
|
{ LOGD_DCB, "DCB" },
|
|
|
|
|
{ LOGD_DISPATCH, "DISPATCH" },
|
|
|
|
|
{ LOGD_AUDIT, "AUDIT" },
|
|
|
|
|
{ LOGD_SYSTEMD, "SYSTEMD" },
|
|
|
|
|
{ LOGD_VPN_PLUGIN,"VPN_PLUGIN" },
|
|
|
|
|
{ LOGD_PROXY, "PROXY" },
|
|
|
|
|
{ 0 },
|
2010-04-06 15:23:08 -07:00
|
|
|
};
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2010-04-08 08:56:17 -07:00
|
|
|
|
2019-01-19 13:14:38 +01:00
|
|
|
static char *_domains_to_string (gboolean include_level_override,
|
|
|
|
|
NMLogLevel log_level,
|
|
|
|
|
const NMLogDomain log_state[static _LOGL_N_REAL]);
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
|
2016-10-05 15:52:55 +02:00
|
|
|
static gboolean
|
|
|
|
|
_syslog_identifier_valid_domain (const char *domain)
|
|
|
|
|
{
|
|
|
|
|
char c;
|
|
|
|
|
|
|
|
|
|
if (!domain || !domain[0])
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* we pass the syslog identifier as format string. No funny stuff. */
|
|
|
|
|
|
|
|
|
|
for (; (c = domain[0]); domain++) {
|
|
|
|
|
if ( (c >= 'a' && c <= 'z')
|
|
|
|
|
|| (c >= 'A' && c <= 'Z')
|
|
|
|
|
|| (c >= '0' && c <= '9')
|
|
|
|
|
|| NM_IN_SET (c, '-', '_'))
|
|
|
|
|
continue;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2019-01-19 13:14:38 +01:00
|
|
|
_syslog_identifier_assert (const char *syslog_identifier)
|
2016-10-05 15:52:55 +02:00
|
|
|
{
|
2019-01-19 13:14:38 +01:00
|
|
|
g_assert (syslog_identifier);
|
|
|
|
|
g_assert (g_str_has_prefix (syslog_identifier, "SYSLOG_IDENTIFIER="));
|
|
|
|
|
g_assert (_syslog_identifier_valid_domain (&syslog_identifier[NM_STRLEN ("SYSLOG_IDENTIFIER=")]));
|
2016-10-05 15:52:55 +02:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
2019-01-19 13:14:38 +01:00
|
|
|
syslog_identifier_domain (const char *syslog_identifier)
|
2016-10-05 15:52:55 +02:00
|
|
|
{
|
2019-01-19 13:14:38 +01:00
|
|
|
nm_assert (_syslog_identifier_assert (syslog_identifier));
|
|
|
|
|
return &syslog_identifier[NM_STRLEN ("SYSLOG_IDENTIFIER=")];
|
2016-10-05 15:52:55 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-11 10:42:22 +02:00
|
|
|
#if SYSTEMD_JOURNAL
|
2016-10-05 15:52:55 +02:00
|
|
|
static const char *
|
2019-01-19 13:14:38 +01:00
|
|
|
syslog_identifier_full (const char *syslog_identifier)
|
2016-10-05 15:52:55 +02:00
|
|
|
{
|
2019-01-19 13:14:38 +01:00
|
|
|
nm_assert (_syslog_identifier_assert (syslog_identifier));
|
|
|
|
|
return &syslog_identifier[0];
|
2016-10-05 15:52:55 +02:00
|
|
|
}
|
2016-10-11 10:42:22 +02:00
|
|
|
#endif
|
2016-10-05 15:52:55 +02:00
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2013-10-01 11:40:22 -04:00
|
|
|
static gboolean
|
|
|
|
|
match_log_level (const char *level,
|
2014-10-30 12:44:36 +01:00
|
|
|
NMLogLevel *out_level,
|
2013-10-01 11:40:22 -04:00
|
|
|
GError **error)
|
|
|
|
|
{
|
2019-11-22 17:27:00 +01:00
|
|
|
if (_nm_log_parse_level (level, out_level))
|
|
|
|
|
return TRUE;
|
2013-10-01 11:40:22 -04:00
|
|
|
|
2014-10-16 16:47:30 -04:00
|
|
|
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL,
|
2013-10-01 11:40:22 -04:00
|
|
|
_("Unknown log level '%s'"), level);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-06 15:23:08 -07:00
|
|
|
gboolean
|
2013-11-26 11:33:42 -05:00
|
|
|
nm_logging_setup (const char *level,
|
|
|
|
|
const char *domains,
|
|
|
|
|
char **bad_domains,
|
|
|
|
|
GError **error)
|
2010-04-06 15:23:08 -07:00
|
|
|
{
|
2013-11-26 11:33:42 -05:00
|
|
|
GString *unrecognized = NULL;
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
NMLogDomain cur_log_state[_LOGL_N_REAL];
|
|
|
|
|
NMLogDomain new_log_state[_LOGL_N_REAL];
|
|
|
|
|
NMLogLevel cur_log_level;
|
|
|
|
|
NMLogLevel new_log_level;
|
2019-04-04 13:06:00 +02:00
|
|
|
gs_free const char **domains_v = NULL;
|
|
|
|
|
gsize i_d;
|
2013-10-01 11:40:22 -04:00
|
|
|
int i;
|
2015-10-06 19:48:35 +02:00
|
|
|
gboolean had_platform_debug;
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
gs_free char *domains_free = NULL;
|
2010-04-06 15:23:08 -07:00
|
|
|
|
2019-01-15 18:35:25 +01:00
|
|
|
NM_ASSERT_ON_MAIN_THREAD ();
|
|
|
|
|
|
2014-02-12 11:05:02 +01:00
|
|
|
g_return_val_if_fail (!bad_domains || !*bad_domains, FALSE);
|
|
|
|
|
g_return_val_if_fail (!error || !*error, FALSE);
|
|
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
cur_log_level = gl.imm.log_level;
|
|
|
|
|
memcpy (cur_log_state, _nm_logging_enabled_state, sizeof (cur_log_state));
|
|
|
|
|
|
|
|
|
|
new_log_level = cur_log_level;
|
|
|
|
|
|
2019-01-19 13:14:38 +01:00
|
|
|
if (!domains || !*domains) {
|
|
|
|
|
domains_free = _domains_to_string (FALSE,
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
cur_log_level,
|
|
|
|
|
cur_log_state);
|
2019-01-19 13:14:38 +01:00
|
|
|
domains = domains_free;
|
|
|
|
|
}
|
2014-04-05 09:38:59 -04:00
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (new_log_state); i++)
|
|
|
|
|
new_log_state[i] = 0;
|
2010-04-06 15:23:08 -07:00
|
|
|
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
if (level && *level) {
|
2013-10-01 11:40:22 -04:00
|
|
|
if (!match_log_level (level, &new_log_level, error))
|
2010-04-06 15:53:37 -07:00
|
|
|
return FALSE;
|
2015-10-07 10:45:28 +02:00
|
|
|
if (new_log_level == _LOGL_KEEP) {
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
new_log_level = cur_log_level;
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (new_log_state); i++)
|
|
|
|
|
new_log_state[i] = cur_log_state[i];
|
2015-10-07 10:45:28 +02:00
|
|
|
}
|
2010-04-06 15:23:08 -07:00
|
|
|
}
|
|
|
|
|
|
2019-04-04 13:06:00 +02:00
|
|
|
domains_v = nm_utils_strsplit_set (domains, ", ");
|
|
|
|
|
for (i_d = 0; domains_v && domains_v[i_d]; i_d++) {
|
|
|
|
|
const char *s = domains_v[i_d];
|
|
|
|
|
const char *p;
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
const LogDesc *diter;
|
2014-10-30 12:44:36 +01:00
|
|
|
NMLogLevel domain_log_level;
|
|
|
|
|
NMLogDomain bits;
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
|
2016-06-16 22:30:41 +02:00
|
|
|
/* LOGD_VPN_PLUGIN is protected, that is, when setting ALL or DEFAULT,
|
|
|
|
|
* it does not enable the verbose levels DEBUG and TRACE, because that
|
|
|
|
|
* may expose sensitive data. */
|
|
|
|
|
NMLogDomain protect = LOGD_NONE;
|
|
|
|
|
|
2019-04-04 13:06:00 +02:00
|
|
|
p = strchr (s, ':');
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
if (p) {
|
2019-04-04 13:06:00 +02:00
|
|
|
*((char *) p) = '\0';
|
|
|
|
|
if (!match_log_level (p + 1, &domain_log_level, error))
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
return FALSE;
|
|
|
|
|
} else
|
|
|
|
|
domain_log_level = new_log_level;
|
|
|
|
|
|
|
|
|
|
bits = 0;
|
|
|
|
|
|
2016-10-06 21:40:18 +02:00
|
|
|
if (domains_free) {
|
|
|
|
|
/* The caller didn't provide any domains to set (`nmcli general logging level DEBUG`).
|
|
|
|
|
* We reset all domains that were previously set, but we still want to protect
|
|
|
|
|
* VPN_PLUGIN domain. */
|
|
|
|
|
protect = LOGD_VPN_PLUGIN;
|
|
|
|
|
}
|
|
|
|
|
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
/* Check for combined domains */
|
2019-04-04 13:06:00 +02:00
|
|
|
if (!g_ascii_strcasecmp (s, LOGD_ALL_STRING)) {
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
bits = LOGD_ALL;
|
2016-06-16 22:30:41 +02:00
|
|
|
protect = LOGD_VPN_PLUGIN;
|
2019-04-04 13:06:00 +02:00
|
|
|
} else if (!g_ascii_strcasecmp (s, LOGD_DEFAULT_STRING)) {
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
bits = LOGD_DEFAULT;
|
2016-06-16 22:30:41 +02:00
|
|
|
protect = LOGD_VPN_PLUGIN;
|
2019-04-04 13:06:00 +02:00
|
|
|
} else if (!g_ascii_strcasecmp (s, LOGD_DHCP_STRING))
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
bits = LOGD_DHCP;
|
2019-04-04 13:06:00 +02:00
|
|
|
else if (!g_ascii_strcasecmp (s, LOGD_IP_STRING))
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
bits = LOGD_IP;
|
|
|
|
|
|
|
|
|
|
/* Check for compatibility domains */
|
2019-04-04 13:06:00 +02:00
|
|
|
else if (!g_ascii_strcasecmp (s, "HW"))
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
bits = LOGD_PLATFORM;
|
2019-04-04 13:06:00 +02:00
|
|
|
else if (!g_ascii_strcasecmp (s, "WIMAX"))
|
wimax: drop WiMAX support (bgo #747846)
Even Fedora is no longer shipping the WiMAX SDK, so it's likely we'll
eventually accidentally break some of the code in src/devices/wimax/
(if we haven't already). Discussion on the list showed a consensus for
dropping support for WiMAX.
So, remove the SDK checks from configure.ac, remove the WiMAX device
plugin and associated manager support, and deprecate all the APIs.
For compatibility reasons, it is still possible to create and save
WiMAX connections, to toggle the software WiMAX rfkill state, and to
change the "WIMAX" log level, although none of these have any effect,
since no NMDeviceWimax will ever be created.
nmcli was only compiling in support for most WiMAX operations when NM
as a whole was built with WiMAX support, so that code has been removed
now as well. (It is still possible to use nmcli to create and edit
WiMAX connections, but those connections will never be activatable.)
2015-04-13 17:07:00 -04:00
|
|
|
continue;
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
|
|
|
|
|
else {
|
2019-01-15 16:58:15 +01:00
|
|
|
for (diter = &domain_desc[0]; diter->name; diter++) {
|
2019-04-04 13:06:00 +02:00
|
|
|
if (!g_ascii_strcasecmp (diter->name, s)) {
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
bits = diter->num;
|
|
|
|
|
break;
|
2013-11-26 11:33:42 -05:00
|
|
|
}
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
}
|
2013-11-26 11:33:42 -05:00
|
|
|
|
2015-08-01 14:35:51 +02:00
|
|
|
if (!bits) {
|
|
|
|
|
if (!bad_domains) {
|
|
|
|
|
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN,
|
2019-04-04 13:06:00 +02:00
|
|
|
_("Unknown log domain '%s'"), s);
|
2015-08-01 14:35:51 +02:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
2013-10-01 11:40:22 -04:00
|
|
|
|
2015-08-01 14:35:51 +02:00
|
|
|
if (unrecognized)
|
|
|
|
|
g_string_append (unrecognized, ", ");
|
|
|
|
|
else
|
|
|
|
|
unrecognized = g_string_new (NULL);
|
2019-04-04 13:06:00 +02:00
|
|
|
g_string_append (unrecognized, s);
|
2015-08-01 14:35:51 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
2010-04-06 15:23:08 -07:00
|
|
|
}
|
2013-10-01 11:40:22 -04:00
|
|
|
|
2015-10-07 10:45:28 +02:00
|
|
|
if (domain_log_level == _LOGL_KEEP) {
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (new_log_state); i++)
|
|
|
|
|
new_log_state[i] = (new_log_state[i] & ~bits) | (cur_log_state[i] & bits);
|
2015-10-07 10:45:28 +02:00
|
|
|
} else {
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (new_log_state); i++) {
|
2015-10-07 10:45:28 +02:00
|
|
|
if (i < domain_log_level)
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
new_log_state[i] &= ~bits;
|
2016-06-16 22:30:41 +02:00
|
|
|
else {
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
new_log_state[i] |= bits;
|
2016-10-06 21:40:18 +02:00
|
|
|
if ( (protect & bits)
|
2016-06-16 22:30:41 +02:00
|
|
|
&& i < LOGL_INFO)
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
new_log_state[i] &= ~protect;
|
2016-06-16 22:30:41 +02:00
|
|
|
}
|
2015-10-07 10:45:28 +02:00
|
|
|
}
|
2015-08-01 14:12:34 +02:00
|
|
|
}
|
logging: fix "nmcli gen log level FOO"
The change to per-domain log levels means that when setting just the
level, we need to re-set the log level for each domain (since it's the
"logging" bit array that actually determines what gets logged).
nm_logging_setup() was dealing correctly with domains=NULL, but not
domains="" (which is what happens when it is invoked with only a level
via D-Bus), so doing "nmcli gen log level DEBUG" would change the
"default" log level, but leave all of the domains still at their
previous level:
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
INFO PLATFORM,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,IP4,IP6...
danw@laptop:NetworkManager> nmcli g log level DEBUG
danw@laptop:NetworkManager> nmcli g log
LEVEL DOMAINS
DEBUG PLATFORM:INFO,RFKILL:INFO,ETHER:INFO,WIFI:INFO,BT:INFO...
2014-01-21 09:54:50 -05:00
|
|
|
}
|
2013-10-01 11:40:22 -04:00
|
|
|
|
2019-01-15 18:35:25 +01:00
|
|
|
g_clear_pointer (&gl_main.logging_domains_to_string, g_free);
|
2014-02-12 11:30:29 +01:00
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
had_platform_debug = _nm_logging_enabled_lockfree (LOGL_DEBUG, LOGD_PLATFORM);
|
|
|
|
|
|
|
|
|
|
G_LOCK (log);
|
2015-10-06 19:48:35 +02:00
|
|
|
|
2019-01-15 14:27:37 +01:00
|
|
|
gl.mut.log_level = new_log_level;
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (new_log_state); i++)
|
|
|
|
|
_nm_logging_enabled_state[i] = new_log_state[i];
|
|
|
|
|
|
|
|
|
|
G_UNLOCK (log);
|
2013-10-01 11:40:22 -04:00
|
|
|
|
2015-10-06 19:48:35 +02:00
|
|
|
if ( had_platform_debug
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
&& !_nm_logging_enabled_lockfree (LOGL_DEBUG, LOGD_PLATFORM)) {
|
2015-10-06 19:48:35 +02:00
|
|
|
/* when debug logging is enabled, platform will cache all access to
|
|
|
|
|
* sysctl. When the user disables debug-logging, we want to clear that
|
|
|
|
|
* cache right away. */
|
2016-03-01 10:17:44 +01:00
|
|
|
_nm_logging_clear_platform_logging_cache ();
|
2015-10-06 19:48:35 +02:00
|
|
|
}
|
|
|
|
|
|
2013-11-26 11:33:42 -05:00
|
|
|
if (unrecognized)
|
|
|
|
|
*bad_domains = g_string_free (unrecognized, FALSE);
|
|
|
|
|
|
2010-04-06 15:23:08 -07:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-12 11:17:26 +01:00
|
|
|
const char *
|
2010-05-04 12:06:00 -07:00
|
|
|
nm_logging_level_to_string (void)
|
|
|
|
|
{
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
NM_ASSERT_ON_MAIN_THREAD ();
|
|
|
|
|
|
2019-01-15 14:27:37 +01:00
|
|
|
return level_desc[gl.imm.log_level].name;
|
2010-05-04 12:06:00 -07:00
|
|
|
}
|
|
|
|
|
|
2013-03-11 12:23:57 -04:00
|
|
|
const char *
|
|
|
|
|
nm_logging_all_levels_to_string (void)
|
|
|
|
|
{
|
|
|
|
|
static GString *str;
|
|
|
|
|
|
|
|
|
|
if (G_UNLIKELY (!str)) {
|
2013-10-01 11:40:22 -04:00
|
|
|
int i;
|
2013-03-11 12:23:57 -04:00
|
|
|
|
|
|
|
|
str = g_string_new (NULL);
|
2019-01-15 16:58:15 +01:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (level_desc); i++) {
|
2013-03-11 12:23:57 -04:00
|
|
|
if (str->len)
|
|
|
|
|
g_string_append_c (str, ',');
|
2019-01-15 16:58:15 +01:00
|
|
|
g_string_append (str, level_desc[i].name);
|
2013-03-11 12:23:57 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return str->str;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-12 11:30:29 +01:00
|
|
|
const char *
|
2010-05-04 12:06:00 -07:00
|
|
|
nm_logging_domains_to_string (void)
|
|
|
|
|
{
|
2019-01-15 18:35:25 +01:00
|
|
|
NM_ASSERT_ON_MAIN_THREAD ();
|
|
|
|
|
|
2019-01-19 13:14:38 +01:00
|
|
|
if (G_UNLIKELY (!gl_main.logging_domains_to_string)) {
|
|
|
|
|
gl_main.logging_domains_to_string = _domains_to_string (TRUE,
|
|
|
|
|
gl.imm.log_level,
|
|
|
|
|
_nm_logging_enabled_state);
|
|
|
|
|
}
|
2013-10-01 11:40:22 -04:00
|
|
|
|
2019-01-15 18:35:25 +01:00
|
|
|
return gl_main.logging_domains_to_string;
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
}
|
2010-05-04 12:06:00 -07:00
|
|
|
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
static char *
|
2019-01-19 13:14:38 +01:00
|
|
|
_domains_to_string (gboolean include_level_override,
|
|
|
|
|
NMLogLevel log_level,
|
|
|
|
|
const NMLogDomain log_state[static _LOGL_N_REAL])
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
{
|
|
|
|
|
const LogDesc *diter;
|
|
|
|
|
GString *str;
|
|
|
|
|
int i;
|
2013-10-01 11:40:22 -04:00
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
/* We don't just return g_strdup() the logging domains that were set during
|
|
|
|
|
* nm_logging_setup(), because we want to expand "DEFAULT" and "ALL".
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
str = g_string_sized_new (75);
|
2019-01-15 16:58:15 +01:00
|
|
|
for (diter = &domain_desc[0]; diter->name; diter++) {
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
/* If it's set for any lower level, it will also be set for LOGL_ERR */
|
2019-01-19 13:14:38 +01:00
|
|
|
if (!(diter->num & log_state[LOGL_ERR]))
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (str->len)
|
|
|
|
|
g_string_append_c (str, ',');
|
|
|
|
|
g_string_append (str, diter->name);
|
2013-10-01 11:40:22 -04:00
|
|
|
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
if (!include_level_override)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* Check if it's logging at a lower level than the default. */
|
2019-01-19 13:14:38 +01:00
|
|
|
for (i = 0; i < log_level; i++) {
|
|
|
|
|
if (diter->num & log_state[i]) {
|
2019-01-15 16:58:15 +01:00
|
|
|
g_string_append_printf (str, ":%s", level_desc[i].name);
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Check if it's logging at a higher level than the default. */
|
2019-01-19 13:14:38 +01:00
|
|
|
if (!(diter->num & log_state[log_level])) {
|
|
|
|
|
for (i = log_level + 1; i < _LOGL_N_REAL; i++) {
|
|
|
|
|
if (diter->num & log_state[i]) {
|
2019-01-15 16:58:15 +01:00
|
|
|
g_string_append_printf (str, ":%s", level_desc[i].name);
|
2013-10-01 11:40:22 -04:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-05-04 12:06:00 -07:00
|
|
|
}
|
|
|
|
|
}
|
logging: properly use current domains when setting logging
When setting the logging with omitting the domains, we would
use the previously set logging domains. That was wrong since
the addition of the 'KEEP' level:
(1) $ nmcli g l level INFO domains DNS,CORE
$ nmcli g l
LEVEL DOMAINS
INFO DNS,CORE
(2) $ nmcli g l level KEEP domains PPP:TRACE
$ nmcli g l
LEVEL DOMAINS
INFO PPP:TRACE,DNS,CORE
(3) $ nmcli g l level ERR
$ nmcli g l
LEVEL DOMAINS
ERR PPP:TRACE
with this change, command (3) effectively translates to:
$ nmcli g l level ERR domains PPP,DNS,CORE
$ nmcli g l
LEVEL DOMAINS
ERR PPP,DNS,CORE
2015-10-09 12:36:29 +02:00
|
|
|
return g_string_free (str, FALSE);
|
2010-05-04 12:06:00 -07:00
|
|
|
}
|
|
|
|
|
|
2019-05-14 12:56:44 +02:00
|
|
|
static char _all_logging_domains_to_str[273];
|
|
|
|
|
|
2013-03-11 12:23:57 -04:00
|
|
|
const char *
|
|
|
|
|
nm_logging_all_domains_to_string (void)
|
|
|
|
|
{
|
2019-05-14 12:56:44 +02:00
|
|
|
static const char *volatile str = NULL;
|
|
|
|
|
const char *s;
|
2013-03-11 12:23:57 -04:00
|
|
|
|
2019-05-14 12:56:44 +02:00
|
|
|
again:
|
|
|
|
|
s = g_atomic_pointer_get (&str);
|
|
|
|
|
if (G_UNLIKELY (!s)) {
|
|
|
|
|
static gsize once = 0;
|
2013-03-11 12:23:57 -04:00
|
|
|
const LogDesc *diter;
|
2019-05-14 12:56:44 +02:00
|
|
|
gsize buf_l;
|
|
|
|
|
char *buf_p;
|
|
|
|
|
|
|
|
|
|
if (!g_once_init_enter (&once))
|
|
|
|
|
goto again;
|
|
|
|
|
|
|
|
|
|
buf_p = _all_logging_domains_to_str;
|
|
|
|
|
buf_l = sizeof (_all_logging_domains_to_str);
|
2013-03-11 12:23:57 -04:00
|
|
|
|
2019-05-14 12:56:44 +02:00
|
|
|
nm_utils_strbuf_append_str (&buf_p, &buf_l, LOGD_DEFAULT_STRING);
|
2019-01-15 16:58:15 +01:00
|
|
|
for (diter = &domain_desc[0]; diter->name; diter++) {
|
2019-05-14 12:56:44 +02:00
|
|
|
nm_utils_strbuf_append_c (&buf_p, &buf_l, ',');
|
|
|
|
|
nm_utils_strbuf_append_str (&buf_p, &buf_l, diter->name);
|
2013-03-11 12:23:57 -04:00
|
|
|
if (diter->num == LOGD_DHCP6)
|
2019-05-14 12:56:44 +02:00
|
|
|
nm_utils_strbuf_append_str (&buf_p, &buf_l, ","LOGD_DHCP_STRING);
|
2013-03-11 12:23:57 -04:00
|
|
|
else if (diter->num == LOGD_IP6)
|
2019-05-14 12:56:44 +02:00
|
|
|
nm_utils_strbuf_append_str (&buf_p, &buf_l, ","LOGD_IP_STRING);
|
2013-03-11 12:23:57 -04:00
|
|
|
}
|
2019-05-14 12:56:44 +02:00
|
|
|
nm_utils_strbuf_append_str (&buf_p, &buf_l, LOGD_ALL_STRING);
|
|
|
|
|
|
|
|
|
|
/* Did you modify the logging domains (or their names)? Adjust the size of
|
|
|
|
|
* _all_logging_domains_to_str buffer above to have the exact size. */
|
|
|
|
|
nm_assert (strlen (_all_logging_domains_to_str) == sizeof (_all_logging_domains_to_str) - 1);
|
|
|
|
|
nm_assert (buf_l == 1);
|
|
|
|
|
|
|
|
|
|
s = _all_logging_domains_to_str;
|
|
|
|
|
g_atomic_pointer_set (&str, s);
|
|
|
|
|
g_once_init_leave (&once, 1);
|
2013-03-11 12:23:57 -04:00
|
|
|
}
|
|
|
|
|
|
2019-05-14 12:56:44 +02:00
|
|
|
return s;
|
2013-03-11 12:23:57 -04:00
|
|
|
}
|
|
|
|
|
|
2016-05-23 10:56:27 +02:00
|
|
|
/**
|
|
|
|
|
* nm_logging_get_level:
|
|
|
|
|
* @domain: find the lowest enabled logging level for the
|
|
|
|
|
* given domain. If this is a set of multiple
|
|
|
|
|
* domains, the most verbose level will be returned.
|
|
|
|
|
*
|
|
|
|
|
* Returns: the lowest (most verbose) logging level for the
|
|
|
|
|
* give @domain, or %_LOGL_OFF if it is disabled.
|
|
|
|
|
**/
|
|
|
|
|
NMLogLevel
|
|
|
|
|
nm_logging_get_level (NMLogDomain domain)
|
|
|
|
|
{
|
|
|
|
|
NMLogLevel sl = _LOGL_OFF;
|
|
|
|
|
|
|
|
|
|
G_STATIC_ASSERT (LOGL_TRACE == 0);
|
|
|
|
|
while ( sl > LOGL_TRACE
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
&& _nm_logging_enabled_lockfree (sl - 1, domain))
|
2016-05-23 10:56:27 +02:00
|
|
|
sl--;
|
|
|
|
|
return sl;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-28 15:31:23 +01:00
|
|
|
gboolean
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
_nm_logging_enabled_locking (NMLogLevel level,
|
|
|
|
|
NMLogDomain domain)
|
2018-12-28 15:31:23 +01:00
|
|
|
{
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
gboolean v;
|
|
|
|
|
|
|
|
|
|
G_LOCK (log);
|
|
|
|
|
v = _nm_logging_enabled_lockfree (level, domain);
|
|
|
|
|
G_UNLOCK (log);
|
|
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
_nm_log_enabled_impl (gboolean mt_require_locking,
|
|
|
|
|
NMLogLevel level,
|
|
|
|
|
NMLogDomain domain)
|
|
|
|
|
{
|
|
|
|
|
return nm_logging_enabled_mt (mt_require_locking, level, domain);
|
2018-12-28 15:31:23 +01:00
|
|
|
}
|
|
|
|
|
|
2015-07-08 16:21:21 +02:00
|
|
|
#if SYSTEMD_JOURNAL
|
|
|
|
|
static void
|
2016-10-06 16:55:12 +02:00
|
|
|
_iovec_set (struct iovec *iov, const void *str, gsize len)
|
2015-07-08 16:21:21 +02:00
|
|
|
{
|
2016-10-06 16:55:12 +02:00
|
|
|
iov->iov_base = (void *) str;
|
|
|
|
|
iov->iov_len = len;
|
2015-07-08 16:21:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2016-10-06 16:55:12 +02:00
|
|
|
_iovec_set_string (struct iovec *iov, const char *str)
|
2015-07-08 16:21:21 +02:00
|
|
|
{
|
2016-10-06 16:55:12 +02:00
|
|
|
_iovec_set (iov, str, strlen (str));
|
2015-07-08 16:21:21 +02:00
|
|
|
}
|
2016-10-05 15:52:55 +02:00
|
|
|
|
2019-05-14 12:28:22 +02:00
|
|
|
#define _iovec_set_string_literal(iov, str) _iovec_set ((iov), ""str"", NM_STRLEN (str))
|
|
|
|
|
|
2016-10-06 16:55:12 +02:00
|
|
|
_nm_printf (3, 4)
|
2016-10-05 15:52:55 +02:00
|
|
|
static void
|
2019-05-14 13:40:04 +02:00
|
|
|
_iovec_set_format (struct iovec *iov, char **iov_free, const char *format, ...)
|
2016-10-05 15:52:55 +02:00
|
|
|
{
|
2016-10-06 16:55:12 +02:00
|
|
|
va_list ap;
|
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
|
|
va_start (ap, format);
|
|
|
|
|
str = g_strdup_vprintf (format, ap);
|
|
|
|
|
va_end (ap);
|
|
|
|
|
|
|
|
|
|
_iovec_set_string (iov, str);
|
|
|
|
|
*iov_free = str;
|
2016-10-05 15:52:55 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-06 16:55:12 +02:00
|
|
|
#define _iovec_set_format_a(iov, reserve_extra, format, ...) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
const gsize _size = (reserve_extra) + (NM_STRLEN (format) + 3); \
|
|
|
|
|
char *const _buf = g_alloca (_size); \
|
|
|
|
|
int _len; \
|
|
|
|
|
\
|
2019-01-10 12:00:34 +01:00
|
|
|
G_STATIC_ASSERT_EXPR ((reserve_extra) + (NM_STRLEN (format) + 3) <= 96); \
|
|
|
|
|
\
|
2016-10-06 16:55:12 +02:00
|
|
|
_len = g_snprintf (_buf, _size, ""format"", ##__VA_ARGS__);\
|
|
|
|
|
\
|
|
|
|
|
nm_assert (_len >= 0); \
|
2019-01-10 12:00:34 +01:00
|
|
|
nm_assert (_len < _size); \
|
2016-10-06 16:55:12 +02:00
|
|
|
nm_assert (_len == strlen (_buf)); \
|
|
|
|
|
\
|
|
|
|
|
_iovec_set ((iov), _buf, _len); \
|
|
|
|
|
} G_STMT_END
|
2019-01-10 12:00:34 +01:00
|
|
|
|
|
|
|
|
#define _iovec_set_format_str_a(iov, max_str_len, format, str_arg) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
const char *_str_arg = (str_arg); \
|
|
|
|
|
\
|
|
|
|
|
nm_assert (_str_arg && strlen (_str_arg) < (max_str_len)); \
|
|
|
|
|
_iovec_set_format_a ((iov), (max_str_len), format, str_arg); \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
2015-07-08 16:21:21 +02:00
|
|
|
#endif
|
|
|
|
|
|
2011-03-19 12:42:29 -05:00
|
|
|
void
|
2015-04-22 11:06:49 +02:00
|
|
|
_nm_log_impl (const char *file,
|
|
|
|
|
guint line,
|
|
|
|
|
const char *func,
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
gboolean mt_require_locking,
|
2015-04-22 11:06:49 +02:00
|
|
|
NMLogLevel level,
|
|
|
|
|
NMLogDomain domain,
|
|
|
|
|
int error,
|
2017-03-01 10:20:01 +00:00
|
|
|
const char *ifname,
|
|
|
|
|
const char *conn_uuid,
|
2015-04-22 11:06:49 +02:00
|
|
|
const char *fmt,
|
|
|
|
|
...)
|
2010-04-06 15:23:08 -07:00
|
|
|
{
|
|
|
|
|
va_list args;
|
|
|
|
|
char *msg;
|
|
|
|
|
GTimeVal tv;
|
2019-01-31 13:29:21 +01:00
|
|
|
int errsv;
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
const NMLogDomain *cur_log_state;
|
|
|
|
|
NMLogDomain cur_log_state_copy[_LOGL_N_REAL];
|
|
|
|
|
Global g_copy;
|
|
|
|
|
const Global *g;
|
|
|
|
|
|
|
|
|
|
if (G_UNLIKELY (mt_require_locking)) {
|
|
|
|
|
G_LOCK (log);
|
|
|
|
|
/* we evaluate logging-enabled under lock. There is still a race that
|
|
|
|
|
* we might log the message below *after* logging was disabled. That means,
|
|
|
|
|
* when disabling logging, we might still log messages. */
|
|
|
|
|
if (!_nm_logging_enabled_lockfree (level, domain)) {
|
|
|
|
|
G_UNLOCK (log);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
g_copy = gl.imm;
|
|
|
|
|
memcpy (cur_log_state_copy, _nm_logging_enabled_state, sizeof (cur_log_state_copy));
|
|
|
|
|
G_UNLOCK (log);
|
|
|
|
|
g = &g_copy;
|
|
|
|
|
cur_log_state = cur_log_state_copy;
|
|
|
|
|
} else {
|
|
|
|
|
NM_ASSERT_ON_MAIN_THREAD ();
|
|
|
|
|
if (!_nm_logging_enabled_lockfree (level, domain))
|
|
|
|
|
return;
|
|
|
|
|
g = &gl.imm;
|
|
|
|
|
cur_log_state = _nm_logging_enabled_state;
|
|
|
|
|
}
|
2010-04-06 15:23:08 -07:00
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
(void) cur_log_state;
|
2010-04-06 15:23:08 -07:00
|
|
|
|
2019-01-31 13:29:21 +01:00
|
|
|
errsv = errno;
|
2016-12-11 22:33:19 +01:00
|
|
|
|
2014-12-05 00:54:30 +01:00
|
|
|
/* Make sure that %m maps to the specified error */
|
2015-09-23 16:03:41 +02:00
|
|
|
if (error != 0) {
|
|
|
|
|
if (error < 0)
|
|
|
|
|
error = -error;
|
2014-12-05 00:54:30 +01:00
|
|
|
errno = error;
|
2015-09-23 16:03:41 +02:00
|
|
|
}
|
2014-12-05 00:54:30 +01:00
|
|
|
|
2010-04-06 15:23:08 -07:00
|
|
|
va_start (args, fmt);
|
|
|
|
|
msg = g_strdup_vprintf (fmt, args);
|
|
|
|
|
va_end (args);
|
|
|
|
|
|
2016-10-06 15:55:01 +02:00
|
|
|
#define MESSAGE_FMT "%s%-7s [%ld.%04ld] %s"
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
#define MESSAGE_ARG(prefix, tv, msg) \
|
|
|
|
|
prefix, \
|
2019-01-15 16:58:15 +01:00
|
|
|
level_desc[level].level_str, \
|
2016-10-06 15:55:01 +02:00
|
|
|
(tv).tv_sec, \
|
|
|
|
|
((tv).tv_usec / 100), \
|
|
|
|
|
(msg)
|
|
|
|
|
|
2016-08-19 12:06:23 +02:00
|
|
|
g_get_current_time (&tv);
|
2016-02-13 16:27:11 +01:00
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
if (g->debug_stderr)
|
|
|
|
|
g_printerr (MESSAGE_FMT"\n", MESSAGE_ARG (g->prefix, tv, msg));
|
2017-03-01 13:34:32 +01:00
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
switch (g->log_backend) {
|
2015-07-08 16:21:21 +02:00
|
|
|
#if SYSTEMD_JOURNAL
|
|
|
|
|
case LOG_BACKEND_JOURNAL:
|
|
|
|
|
{
|
|
|
|
|
gint64 now, boottime;
|
2019-05-14 12:28:22 +02:00
|
|
|
struct iovec iov_data[15];
|
2016-10-06 16:55:12 +02:00
|
|
|
struct iovec *iov = iov_data;
|
2019-05-14 13:40:04 +02:00
|
|
|
char *iov_free_data[5];
|
|
|
|
|
char **iov_free = iov_free_data;
|
2020-02-12 16:19:46 +01:00
|
|
|
const LogDesc *diter;
|
|
|
|
|
NMLogDomain dom_all;
|
|
|
|
|
char s_log_domains_buf[NM_STRLEN ("NM_LOG_DOMAINS=") + sizeof (_all_logging_domains_to_str)];
|
|
|
|
|
char *s_log_domains;
|
|
|
|
|
gsize l_log_domains;
|
2015-07-08 16:21:21 +02:00
|
|
|
|
2019-12-13 16:54:30 +01:00
|
|
|
now = nm_utils_get_monotonic_timestamp_nsec ();
|
2015-07-08 16:21:21 +02:00
|
|
|
boottime = nm_utils_monotonic_timestamp_as_boottime (now, 1);
|
|
|
|
|
|
2019-01-15 16:58:15 +01:00
|
|
|
_iovec_set_format_a (iov++, 30, "PRIORITY=%d", level_desc[level].syslog_level);
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
_iovec_set_format (iov++, iov_free++, "MESSAGE="MESSAGE_FMT, MESSAGE_ARG (g->prefix, tv, msg));
|
|
|
|
|
_iovec_set_string (iov++, syslog_identifier_full (g->syslog_identifier));
|
2016-10-06 16:55:12 +02:00
|
|
|
_iovec_set_format_a (iov++, 30, "SYSLOG_PID=%ld", (long) getpid ());
|
2020-02-12 16:19:46 +01:00
|
|
|
|
|
|
|
|
dom_all = domain;
|
|
|
|
|
s_log_domains = s_log_domains_buf;
|
|
|
|
|
l_log_domains = sizeof (s_log_domains_buf);
|
|
|
|
|
|
|
|
|
|
nm_utils_strbuf_append_str (&s_log_domains, &l_log_domains, "NM_LOG_DOMAINS=");
|
|
|
|
|
for (diter = &domain_desc[0]; dom_all != 0 && diter->name; diter++) {
|
|
|
|
|
if (!NM_FLAGS_ANY (dom_all, diter->num))
|
|
|
|
|
continue;
|
|
|
|
|
if (dom_all != domain)
|
|
|
|
|
nm_utils_strbuf_append_c (&s_log_domains, &l_log_domains, ',');
|
|
|
|
|
nm_utils_strbuf_append_str (&s_log_domains, &l_log_domains, diter->name);
|
|
|
|
|
dom_all &= ~diter->num;
|
2015-07-08 16:21:21 +02:00
|
|
|
}
|
2020-02-12 16:19:46 +01:00
|
|
|
nm_assert (l_log_domains > 0);
|
|
|
|
|
_iovec_set (iov++, s_log_domains_buf, s_log_domains - s_log_domains_buf);
|
|
|
|
|
|
2019-05-14 12:28:22 +02:00
|
|
|
G_STATIC_ASSERT_EXPR (LOG_FAC (LOG_DAEMON) == 3);
|
|
|
|
|
_iovec_set_string_literal (iov++, "SYSLOG_FACILITY=3");
|
2019-01-15 16:58:15 +01:00
|
|
|
_iovec_set_format_str_a (iov++, 15, "NM_LOG_LEVEL=%s", level_desc[level].name);
|
2016-07-05 18:43:49 +02:00
|
|
|
if (func)
|
2016-10-06 16:55:12 +02:00
|
|
|
_iovec_set_format (iov++, iov_free++, "CODE_FUNC=%s", func);
|
|
|
|
|
_iovec_set_format (iov++, iov_free++, "CODE_FILE=%s", file ?: "");
|
|
|
|
|
_iovec_set_format_a (iov++, 20, "CODE_LINE=%u", line);
|
2019-12-13 16:54:30 +01:00
|
|
|
_iovec_set_format_a (iov++, 60, "TIMESTAMP_MONOTONIC=%lld.%06lld", (long long) (now / NM_UTILS_NSEC_PER_SEC), (long long) ((now % NM_UTILS_NSEC_PER_SEC) / 1000));
|
|
|
|
|
_iovec_set_format_a (iov++, 60, "TIMESTAMP_BOOTTIME=%lld.%06lld", (long long) (boottime / NM_UTILS_NSEC_PER_SEC), (long long) ((boottime % NM_UTILS_NSEC_PER_SEC) / 1000));
|
2015-07-08 16:21:21 +02:00
|
|
|
if (error != 0)
|
2016-10-06 16:55:12 +02:00
|
|
|
_iovec_set_format_a (iov++, 30, "ERRNO=%d", error);
|
2017-03-01 10:20:01 +00:00
|
|
|
if (ifname)
|
|
|
|
|
_iovec_set_format (iov++, iov_free++, "NM_DEVICE=%s", ifname);
|
|
|
|
|
if (conn_uuid)
|
|
|
|
|
_iovec_set_format (iov++, iov_free++, "NM_CONNECTION=%s", conn_uuid);
|
2015-07-08 16:21:21 +02:00
|
|
|
|
2016-10-06 16:55:12 +02:00
|
|
|
nm_assert (iov <= &iov_data[G_N_ELEMENTS (iov_data)]);
|
|
|
|
|
nm_assert (iov_free <= &iov_free_data[G_N_ELEMENTS (iov_free_data)]);
|
2015-07-08 16:21:21 +02:00
|
|
|
|
2016-10-06 16:55:12 +02:00
|
|
|
sd_journal_sendv (iov_data, iov - iov_data);
|
2015-07-08 16:21:21 +02:00
|
|
|
|
2016-10-06 16:55:12 +02:00
|
|
|
for (; --iov_free >= iov_free_data; )
|
|
|
|
|
g_free (*iov_free);
|
2015-07-08 16:21:21 +02:00
|
|
|
}
|
2015-07-08 17:13:59 +02:00
|
|
|
break;
|
2015-07-08 16:21:21 +02:00
|
|
|
#endif
|
2016-10-06 15:55:01 +02:00
|
|
|
case LOG_BACKEND_SYSLOG:
|
2019-01-15 16:58:15 +01:00
|
|
|
syslog (level_desc[level].syslog_level,
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
MESSAGE_FMT, MESSAGE_ARG (g->prefix, tv, msg));
|
2016-10-06 15:55:01 +02:00
|
|
|
break;
|
2015-07-08 17:13:59 +02:00
|
|
|
default:
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
g_log (syslog_identifier_domain (g->syslog_identifier), level_desc[level].g_log_level,
|
|
|
|
|
MESSAGE_FMT, MESSAGE_ARG (g->prefix, tv, msg));
|
2015-07-08 16:21:21 +02:00
|
|
|
break;
|
2015-07-08 17:13:59 +02:00
|
|
|
}
|
2013-06-14 14:51:04 -04:00
|
|
|
|
2010-04-06 15:23:08 -07:00
|
|
|
g_free (msg);
|
2016-12-11 22:33:19 +01:00
|
|
|
|
2019-01-31 13:29:21 +01:00
|
|
|
errno = errsv;
|
2010-04-06 15:23:08 -07:00
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2010-04-06 15:23:08 -07:00
|
|
|
|
2018-10-12 17:16:34 +02:00
|
|
|
void
|
|
|
|
|
_nm_utils_monotonic_timestamp_initialized (const struct timespec *tp,
|
2018-11-25 17:45:11 +01:00
|
|
|
gint64 offset_sec,
|
|
|
|
|
gboolean is_boottime)
|
2018-10-12 17:16:34 +02:00
|
|
|
{
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
NM_ASSERT_ON_MAIN_THREAD ();
|
|
|
|
|
|
|
|
|
|
if (_nm_logging_enabled_lockfree (LOGL_DEBUG, LOGD_CORE)) {
|
2018-10-12 17:16:34 +02:00
|
|
|
time_t now = time (NULL);
|
|
|
|
|
struct tm tm;
|
|
|
|
|
char s[255];
|
|
|
|
|
|
|
|
|
|
strftime (s, sizeof (s), "%Y-%m-%d %H:%M:%S", localtime_r (&now, &tm));
|
|
|
|
|
nm_log_dbg (LOGD_CORE, "monotonic timestamp started counting 1.%09ld seconds ago with "
|
|
|
|
|
"an offset of %lld.0 seconds to %s (local time is %s)",
|
|
|
|
|
tp->tv_nsec,
|
|
|
|
|
(long long) -offset_sec,
|
|
|
|
|
is_boottime ? "CLOCK_BOOTTIME" : "CLOCK_MONOTONIC", s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2006-02-27 04:31:52 +00:00
|
|
|
static void
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
nm_log_handler (const char *log_domain,
|
2010-04-06 15:23:08 -07:00
|
|
|
GLogLevelFlags level,
|
all: don't use gchar/gshort/gint/glong but C types
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
2018-07-11 07:40:19 +02:00
|
|
|
const char *message,
|
2010-04-06 15:23:08 -07:00
|
|
|
gpointer ignored)
|
2006-02-27 04:31:52 +00:00
|
|
|
{
|
2015-07-08 16:21:21 +02:00
|
|
|
int syslog_priority;
|
2006-02-27 04:31:52 +00:00
|
|
|
|
2014-04-24 20:01:13 +02:00
|
|
|
switch (level & G_LOG_LEVEL_MASK) {
|
2010-04-06 15:23:08 -07:00
|
|
|
case G_LOG_LEVEL_ERROR:
|
|
|
|
|
syslog_priority = LOG_CRIT;
|
|
|
|
|
break;
|
|
|
|
|
case G_LOG_LEVEL_CRITICAL:
|
|
|
|
|
syslog_priority = LOG_ERR;
|
|
|
|
|
break;
|
|
|
|
|
case G_LOG_LEVEL_WARNING:
|
|
|
|
|
syslog_priority = LOG_WARNING;
|
|
|
|
|
break;
|
|
|
|
|
case G_LOG_LEVEL_MESSAGE:
|
|
|
|
|
syslog_priority = LOG_NOTICE;
|
|
|
|
|
break;
|
|
|
|
|
case G_LOG_LEVEL_DEBUG:
|
|
|
|
|
syslog_priority = LOG_DEBUG;
|
|
|
|
|
break;
|
|
|
|
|
case G_LOG_LEVEL_INFO:
|
|
|
|
|
default:
|
|
|
|
|
syslog_priority = LOG_INFO;
|
|
|
|
|
break;
|
2006-02-27 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
/* we don't need any locking here. The glib log handler gets only registered
|
|
|
|
|
* once during nm_logging_init() and the global data is not modified afterwards. */
|
|
|
|
|
nm_assert (gl.imm.init_done);
|
|
|
|
|
|
2019-01-15 14:27:37 +01:00
|
|
|
if (gl.imm.debug_stderr)
|
|
|
|
|
g_printerr ("%s%s\n", gl.imm.prefix, message ?: "");
|
2018-02-06 14:47:48 +01:00
|
|
|
|
2019-01-15 14:27:37 +01:00
|
|
|
switch (gl.imm.log_backend) {
|
2015-07-08 16:21:21 +02:00
|
|
|
#if SYSTEMD_JOURNAL
|
|
|
|
|
case LOG_BACKEND_JOURNAL:
|
|
|
|
|
{
|
|
|
|
|
gint64 now, boottime;
|
|
|
|
|
|
2019-12-13 16:54:30 +01:00
|
|
|
now = nm_utils_get_monotonic_timestamp_nsec ();
|
2015-07-08 16:21:21 +02:00
|
|
|
boottime = nm_utils_monotonic_timestamp_as_boottime (now, 1);
|
|
|
|
|
|
|
|
|
|
sd_journal_send ("PRIORITY=%d", syslog_priority,
|
2019-01-15 14:27:37 +01:00
|
|
|
"MESSAGE=%s%s", gl.imm.prefix, message ?: "",
|
2019-01-19 13:14:38 +01:00
|
|
|
syslog_identifier_full (gl.imm.syslog_identifier),
|
2015-07-08 16:21:21 +02:00
|
|
|
"SYSLOG_PID=%ld", (long) getpid (),
|
2019-05-14 12:28:22 +02:00
|
|
|
"SYSLOG_FACILITY=3",
|
2016-03-08 17:41:31 +01:00
|
|
|
"GLIB_DOMAIN=%s", log_domain ?: "",
|
2015-07-08 16:21:21 +02:00
|
|
|
"GLIB_LEVEL=%d", (int) (level & G_LOG_LEVEL_MASK),
|
2019-12-13 16:54:30 +01:00
|
|
|
"TIMESTAMP_MONOTONIC=%lld.%06lld", (long long) (now / NM_UTILS_NSEC_PER_SEC), (long long) ((now % NM_UTILS_NSEC_PER_SEC) / 1000),
|
|
|
|
|
"TIMESTAMP_BOOTTIME=%lld.%06lld", (long long) (boottime / NM_UTILS_NSEC_PER_SEC), (long long) ((boottime % NM_UTILS_NSEC_PER_SEC) / 1000),
|
2015-07-08 16:21:21 +02:00
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
default:
|
2019-01-15 14:27:37 +01:00
|
|
|
syslog (syslog_priority, "%s%s", gl.imm.prefix, message ?: "");
|
2015-07-08 16:21:21 +02:00
|
|
|
break;
|
|
|
|
|
}
|
2006-02-27 04:31:52 +00:00
|
|
|
}
|
|
|
|
|
|
2016-05-23 12:02:31 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_logging_syslog_enabled (void)
|
|
|
|
|
{
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
NM_ASSERT_ON_MAIN_THREAD ();
|
|
|
|
|
|
2019-01-15 14:27:37 +01:00
|
|
|
return gl.imm.uses_syslog;
|
2016-05-23 12:02:31 +02:00
|
|
|
}
|
|
|
|
|
|
2016-10-05 15:25:08 +02:00
|
|
|
void
|
2019-01-16 16:16:49 +01:00
|
|
|
nm_logging_init_pre (const char *syslog_identifier,
|
|
|
|
|
char *prefix_take)
|
2016-10-05 15:25:08 +02:00
|
|
|
{
|
2019-01-16 16:16:49 +01:00
|
|
|
/* this function may be called zero or one times, and only
|
|
|
|
|
* - on the main thread
|
|
|
|
|
* - not after nm_logging_init(). */
|
2016-10-05 15:25:08 +02:00
|
|
|
|
2019-01-16 16:16:49 +01:00
|
|
|
NM_ASSERT_ON_MAIN_THREAD ();
|
|
|
|
|
|
|
|
|
|
if (gl.imm.init_pre_done)
|
2016-10-05 15:25:08 +02:00
|
|
|
g_return_if_reached ();
|
2019-01-16 16:16:49 +01:00
|
|
|
|
|
|
|
|
if (gl.imm.init_done)
|
2016-10-05 15:25:08 +02:00
|
|
|
g_return_if_reached ();
|
|
|
|
|
|
2019-01-16 16:16:49 +01:00
|
|
|
if (!_syslog_identifier_valid_domain (syslog_identifier))
|
|
|
|
|
g_return_if_reached ();
|
2016-10-05 15:25:08 +02:00
|
|
|
|
2019-01-16 16:16:49 +01:00
|
|
|
if (!prefix_take || !prefix_take[0])
|
2016-10-05 15:25:08 +02:00
|
|
|
g_return_if_reached ();
|
|
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
G_LOCK (log);
|
|
|
|
|
|
2019-01-16 16:16:49 +01:00
|
|
|
gl.mut.init_pre_done = TRUE;
|
|
|
|
|
|
|
|
|
|
gl.mut.syslog_identifier = g_strdup_printf ("SYSLOG_IDENTIFIER=%s", syslog_identifier);
|
2019-01-19 13:14:38 +01:00
|
|
|
nm_assert (_syslog_identifier_assert (gl.imm.syslog_identifier));
|
2019-01-16 16:16:49 +01:00
|
|
|
|
2016-10-05 15:25:08 +02:00
|
|
|
/* we pass the allocated string on and never free it. */
|
2019-01-16 16:16:49 +01:00
|
|
|
gl.mut.prefix = prefix_take;
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
|
|
|
|
|
G_UNLOCK (log);
|
2016-10-05 15:25:08 +02:00
|
|
|
}
|
|
|
|
|
|
2006-02-27 04:31:52 +00:00
|
|
|
void
|
2019-01-16 16:16:49 +01:00
|
|
|
nm_logging_init (const char *logging_backend, gboolean debug)
|
2006-02-27 04:31:52 +00:00
|
|
|
{
|
2018-06-21 08:59:23 +02:00
|
|
|
gboolean fetch_monotonic_timestamp = FALSE;
|
2018-06-21 09:21:57 +02:00
|
|
|
gboolean obsolete_debug_backend = FALSE;
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
LogBackend x_log_backend;
|
2018-06-21 09:21:57 +02:00
|
|
|
|
2019-01-16 16:16:49 +01:00
|
|
|
/* this function may be called zero or one times, and only on the
|
|
|
|
|
* main thread. */
|
|
|
|
|
|
|
|
|
|
NM_ASSERT_ON_MAIN_THREAD ();
|
|
|
|
|
|
2018-06-21 09:21:57 +02:00
|
|
|
nm_assert (NM_IN_STRSET (""NM_CONFIG_DEFAULT_LOGGING_BACKEND,
|
|
|
|
|
NM_LOG_CONFIG_BACKEND_JOURNAL,
|
|
|
|
|
NM_LOG_CONFIG_BACKEND_SYSLOG));
|
2018-06-21 08:59:23 +02:00
|
|
|
|
2019-01-16 16:16:49 +01:00
|
|
|
if (gl.imm.init_done)
|
2015-07-08 17:01:15 +02:00
|
|
|
g_return_if_reached ();
|
2015-07-08 17:13:59 +02:00
|
|
|
|
2015-07-08 21:44:01 +02:00
|
|
|
if (!logging_backend)
|
2016-11-25 14:17:30 +01:00
|
|
|
logging_backend = ""NM_CONFIG_DEFAULT_LOGGING_BACKEND;
|
2015-07-08 21:44:01 +02:00
|
|
|
|
2018-06-21 09:21:57 +02:00
|
|
|
if (nm_streq (logging_backend, NM_LOG_CONFIG_BACKEND_DEBUG)) {
|
|
|
|
|
/* "debug" was wrongly documented as a valid logging backend. It makes no sense however,
|
|
|
|
|
* because printing to stderr only makes sense when not demonizing. Whether to daemonize
|
|
|
|
|
* is only controlled via command line arguments (--no-daemon, --debug) and not via the
|
|
|
|
|
* logging backend from configuration.
|
|
|
|
|
*
|
|
|
|
|
* Fall back to the default. */
|
|
|
|
|
logging_backend = ""NM_CONFIG_DEFAULT_LOGGING_BACKEND;
|
|
|
|
|
obsolete_debug_backend = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
|
|
|
|
|
G_LOCK (log);
|
|
|
|
|
|
2015-07-08 16:21:21 +02:00
|
|
|
#if SYSTEMD_JOURNAL
|
2018-06-21 09:21:57 +02:00
|
|
|
if (!nm_streq (logging_backend, NM_LOG_CONFIG_BACKEND_SYSLOG)) {
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
x_log_backend = LOG_BACKEND_JOURNAL;
|
|
|
|
|
|
|
|
|
|
/* We only log the monotonic-timestamp with structured logging (journal).
|
|
|
|
|
* Only in this case, fetch the timestamp. */
|
2018-06-21 08:59:23 +02:00
|
|
|
fetch_monotonic_timestamp = TRUE;
|
2017-03-01 13:34:32 +01:00
|
|
|
} else
|
2015-07-08 16:21:21 +02:00
|
|
|
#endif
|
2017-03-01 13:34:32 +01:00
|
|
|
{
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
x_log_backend = LOG_BACKEND_SYSLOG;
|
2019-01-19 13:14:38 +01:00
|
|
|
openlog (syslog_identifier_domain (gl.imm.syslog_identifier), LOG_PID, LOG_DAEMON);
|
2015-07-08 16:21:21 +02:00
|
|
|
}
|
2013-06-14 14:51:04 -04:00
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
gl.mut.init_done = TRUE;
|
|
|
|
|
gl.mut.log_backend = x_log_backend;
|
|
|
|
|
gl.mut.uses_syslog = TRUE;
|
|
|
|
|
gl.mut.debug_stderr = debug;
|
|
|
|
|
|
2019-01-19 13:14:38 +01:00
|
|
|
g_log_set_handler (syslog_identifier_domain (gl.imm.syslog_identifier),
|
2015-07-08 17:01:15 +02:00
|
|
|
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
|
|
|
|
|
nm_log_handler,
|
|
|
|
|
NULL);
|
2006-02-27 04:31:52 +00:00
|
|
|
|
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop.
However, sometimes we may need multiple threads. For example, we will
need to write sysctl values asynchronously, using the glib thread-pool.
For that to work, we also need to switch the network-namespace of the
thread-pool thread. We want to use NMPNetns for that. Hence it's better
to have NMPNetns thread-safe, instead of coming up with a duplicate
implementation. But NMPNetns may want to log, so we also need nm-logging
thread-safe.
In general, code under "shared/nm-utils" and nm-logging should be usable
from multiple threads. It's simpler to make this code thread-safe than
re-implementing it. Also, it's a bad limitation to be unable to log
from other threads. If there is an error, the best we can often do is to
log about it.
Make nm-logging thread-safe. Actually, we only need to be able to log
from multiple threads. We don't need to setup or configure logging from
multiple threads. This restriction allows us to access logging from the
main-thread without any thread-synchronization (because all changes in
the logging setup are also done from the main-thread).
So, while logging from other threads requires a mutex, logging from the
main-thread is lock-free.
2019-01-16 16:40:45 +01:00
|
|
|
G_UNLOCK (log);
|
|
|
|
|
|
|
|
|
|
|
2018-06-21 08:59:23 +02:00
|
|
|
if (fetch_monotonic_timestamp) {
|
|
|
|
|
/* ensure we read a monotonic timestamp. Reading the timestamp the first
|
|
|
|
|
* time causes a logging message. We don't want to do that during _nm_log_impl. */
|
2019-12-13 16:54:30 +01:00
|
|
|
nm_utils_get_monotonic_timestamp_nsec ();
|
2018-06-21 08:59:23 +02:00
|
|
|
}
|
2018-06-21 09:21:57 +02:00
|
|
|
|
|
|
|
|
if (obsolete_debug_backend)
|
|
|
|
|
nm_log_dbg (LOGD_CORE, "config: ignore deprecated logging backend 'debug', fallback to '%s'", logging_backend);
|
|
|
|
|
|
|
|
|
|
if (nm_streq (logging_backend, NM_LOG_CONFIG_BACKEND_SYSLOG)) {
|
|
|
|
|
/* good */
|
|
|
|
|
} else if (nm_streq (logging_backend, NM_LOG_CONFIG_BACKEND_JOURNAL)) {
|
|
|
|
|
#if !SYSTEMD_JOURNAL
|
|
|
|
|
nm_log_warn (LOGD_CORE, "config: logging backend 'journal' is not available, fallback to 'syslog'");
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
nm_log_warn (LOGD_CORE, "config: invalid logging backend '%s', fallback to '%s'",
|
|
|
|
|
logging_backend,
|
|
|
|
|
#if SYSTEMD_JOURNAL
|
|
|
|
|
NM_LOG_CONFIG_BACKEND_JOURNAL
|
|
|
|
|
#else
|
|
|
|
|
NM_LOG_CONFIG_BACKEND_SYSLOG
|
|
|
|
|
#endif
|
|
|
|
|
);
|
|
|
|
|
}
|
2018-06-21 08:59:23 +02:00
|
|
|
}
|