#include "coverage.h"
#include "dirs.h"
#include "openvswitch/dynamic-string.h"
-#include "ofpbuf.h"
+#include "openvswitch/ofpbuf.h"
#include "ovs-thread.h"
#include "sat-math.h"
#include "socket-util.h"
#include "svec.h"
#include "syslog-direct.h"
#include "syslog-libc.h"
+#include "syslog-null.h"
#include "syslog-provider.h"
#include "timeval.h"
#include "unixctl.h"
vlog_insert_module(struct ovs_list *vlog)
{
ovs_mutex_lock(&log_file_mutex);
- list_insert(&vlog_modules, vlog);
+ ovs_list_insert(&vlog_modules, vlog);
ovs_mutex_unlock(&log_file_mutex);
}
}
static void
-update_min_level(struct vlog_module *module) OVS_REQUIRES(&log_file_mutex)
+update_min_level(struct vlog_module *module) OVS_REQUIRES(log_file_mutex)
{
enum vlog_destination destination;
new_log_file_name = (file_name
? xstrdup(file_name)
: xasprintf("%s/%s.log", ovs_logdir(), program_name));
- new_log_fd = open(new_log_file_name, O_WRONLY | O_CREAT | O_APPEND, 0666);
+ new_log_fd = open(new_log_file_name, O_WRONLY | O_CREAT | O_APPEND, 0660);
if (new_log_fd < 0) {
VLOG_WARN("failed to open %s for logging: %s",
new_log_file_name, ovs_strerror(errno));
/* Close old log file, if any, and install new one. */
ovs_mutex_lock(&log_file_mutex);
if (log_fd >= 0) {
- free(log_file_name);
close(log_fd);
async_append_destroy(log_writer);
}
+ free(log_file_name);
log_file_name = xstrdup(new_log_file_name);
log_fd = new_log_fd;
if (log_async) {
char *fn;
ovs_mutex_lock(&log_file_mutex);
- fn = log_file_name ? xstrdup(log_file_name) : NULL;
+ fn = nullable_xstrdup(log_file_name);
ovs_mutex_unlock(&log_file_mutex);
if (fn) {
return;
}
- if (!strcmp(method, "libc")) {
+ if (!strcmp(method, "null")) {
+ syslogger = syslog_null_create();
+ } else if (!strcmp(method, "libc")) {
syslogger = syslog_libc_create();
} else if (!strncmp(method, "udp:", 4) || !strncmp(method, "unix:", 5)) {
syslogger = syslog_direct_create(method);
{
int new_fd;
- inet_open_active(SOCK_DGRAM, target, 0, NULL, &new_fd, 0);
+ inet_open_active(SOCK_DGRAM, target, -1, NULL, &new_fd, 0);
ovs_rwlock_wrlock(&pattern_rwlock);
if (syslog_fd >= 0) {
ovs_rwlock_unlock(&pattern_rwlock);
}
+/*
+ * This function writes directly to log file without using async writer or
+ * taking a lock. Caller must hold 'log_file_mutex' or be sure that it's
+ * not necessary. Could be used in exceptional cases like dumping of backtrace
+ * on fatal signals.
+ */
+void
+vlog_direct_write_to_log_file_unsafe(const char *s)
+ OVS_NO_THREAD_SAFETY_ANALYSIS
+{
+ if (log_fd >= 0) {
+ ignore(write(log_fd, s, strlen(s)));
+ }
+}
+
/* Returns 'false' if 'facility' is not a valid string. If 'facility'
* is a valid string, sets 'value' with the integer value of 'facility'
* and returns 'true'. */
{
int i;
+ /* With no argument, set all destinations and modules to "dbg". */
+ if (argc == 1) {
+ vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_DBG);
+ }
for (i = 1; i < argc; i++) {
char *msg = vlog_set_levels_from_string(argv[i]);
if (msg) {
* log anything before calling ovsthread_once_done() will deadlock. */
atomic_read_explicit(&log_facility, &facility, memory_order_relaxed);
if (!syslogger) {
- syslogger = syslog_libc_create();
+ char *env = getenv("OVS_SYSLOG_METHOD");
+ if (env && env[0]) {
+ vlog_set_syslog_method(env);
+ } else {
+ syslogger = syslog_libc_create();
+ }
}
syslogger->class->openlog(syslogger, facility ? facility : LOG_DAEMON);
ovsthread_once_done(&once);
unixctl_command_register(
"vlog/set", "{spec | PATTERN:destination:pattern}",
- 1, INT_MAX, vlog_unixctl_set, NULL);
+ 0, INT_MAX, vlog_unixctl_set, NULL);
unixctl_command_register("vlog/list", "", 0, 0, vlog_unixctl_list,
NULL);
unixctl_command_register("vlog/list-pattern", "", 0, 0,
ovs_mutex_unlock(&log_file_mutex);
}
+void
+vlog_disable_async(void)
+{
+ ovs_mutex_lock(&log_file_mutex);
+ log_async = false;
+ async_append_destroy(log_writer);
+ log_writer = NULL;
+ ovs_mutex_unlock(&log_file_mutex);
+}
+
/* Print the current logging level for each module. */
char *
vlog_get_levels(void)
struct ds s = DS_EMPTY_INITIALIZER;
struct vlog_module *mp;
struct svec lines = SVEC_EMPTY_INITIALIZER;
- char *line;
size_t i;
ds_put_format(&s, " console syslog file\n");
ovs_mutex_unlock(&log_file_mutex);
svec_sort(&lines);
+
+ char *line;
SVEC_FOR_EACH (i, line, &lines) {
ds_put_cstr(&s, line);
}
for (p = pattern; *p != '\0'; ) {
const char *subprogram_name;
enum { LEFT, RIGHT } justify = RIGHT;
- int pad = '0';
+ int pad = ' ';
size_t length, field, used;
if (*p != '%') {
{
bool log_to_console = module->levels[VLF_CONSOLE] >= level;
bool log_to_syslog = module->levels[VLF_SYSLOG] >= level;
- bool log_to_file;
+ bool log_to_file = module->levels[VLF_FILE] >= level;
+
+ if (!(log_to_console || log_to_syslog || log_to_file)) {
+ /* fast path - all logging levels specify no logging, no
+ * need to hog the log mutex
+ */
+ return;
+ }
ovs_mutex_lock(&log_file_mutex);
- log_to_file = module->levels[VLF_FILE] >= level && log_fd >= 0;
+ log_to_file &= (log_fd >= 0);
ovs_mutex_unlock(&log_file_mutex);
if (log_to_console || log_to_syslog || log_to_file) {
int save_errno = errno;