mirror of
https://github.com/openvswitch/ovs
synced 2025-10-21 14:49:41 +00:00
ovs-thread: Add support for various thread-related assertions.
Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Ethan Jackson <ethan@nicira.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc.
|
* Copyright (c) 2008, 2009, 2010, 2011, 2013 Nicira, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include "ovs-thread.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "vlog.h"
|
#include "vlog.h"
|
||||||
|
|
||||||
@@ -110,6 +111,7 @@ proctitle_init(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
assert_single_threaded();
|
||||||
if (!argc || !argv[0]) {
|
if (!argc || !argv[0]) {
|
||||||
/* This situation should never occur, but... */
|
/* This situation should never occur, but... */
|
||||||
return;
|
return;
|
||||||
|
12
lib/daemon.c
12
lib/daemon.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
|
* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
#include "fatal-signal.h"
|
#include "fatal-signal.h"
|
||||||
#include "dirs.h"
|
#include "dirs.h"
|
||||||
#include "lockfile.h"
|
#include "lockfile.h"
|
||||||
|
#include "ovs-thread.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
#include "timeval.h"
|
#include "timeval.h"
|
||||||
@@ -88,6 +89,7 @@ make_pidfile_name(const char *name)
|
|||||||
void
|
void
|
||||||
set_pidfile(const char *name)
|
set_pidfile(const char *name)
|
||||||
{
|
{
|
||||||
|
assert_single_threaded();
|
||||||
free(pidfile);
|
free(pidfile);
|
||||||
pidfile = make_pidfile_name(name);
|
pidfile = make_pidfile_name(name);
|
||||||
}
|
}
|
||||||
@@ -280,9 +282,7 @@ daemonize(void)
|
|||||||
pid_t
|
pid_t
|
||||||
fork_and_clean_up(void)
|
fork_and_clean_up(void)
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid = xfork();
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if (pid > 0) {
|
if (pid > 0) {
|
||||||
/* Running in parent process. */
|
/* Running in parent process. */
|
||||||
fatal_signal_fork();
|
fatal_signal_fork();
|
||||||
@@ -290,10 +290,7 @@ fork_and_clean_up(void)
|
|||||||
/* Running in child process. */
|
/* Running in child process. */
|
||||||
time_postfork();
|
time_postfork();
|
||||||
lockfile_postfork();
|
lockfile_postfork();
|
||||||
} else {
|
|
||||||
VLOG_FATAL("fork failed (%s)", strerror(errno));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -504,6 +501,7 @@ close_standard_fds(void)
|
|||||||
void
|
void
|
||||||
daemonize_start(void)
|
daemonize_start(void)
|
||||||
{
|
{
|
||||||
|
assert_single_threaded();
|
||||||
daemonize_fd = -1;
|
daemonize_fd = -1;
|
||||||
|
|
||||||
if (detach) {
|
if (detach) {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include "ofp-util.h"
|
#include "ofp-util.h"
|
||||||
#include "ofp-version-opt.h"
|
#include "ofp-version-opt.h"
|
||||||
|
#include "ovs-thread.h"
|
||||||
#include "vlog.h"
|
#include "vlog.h"
|
||||||
#include "dynamic-string.h"
|
#include "dynamic-string.h"
|
||||||
|
|
||||||
@@ -17,12 +18,14 @@ get_allowed_ofp_versions(void)
|
|||||||
void
|
void
|
||||||
set_allowed_ofp_versions(const char *string)
|
set_allowed_ofp_versions(const char *string)
|
||||||
{
|
{
|
||||||
|
assert_single_threaded();
|
||||||
allowed_versions = ofputil_versions_from_string(string);
|
allowed_versions = ofputil_versions_from_string(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mask_allowed_ofp_versions(uint32_t bitmap)
|
mask_allowed_ofp_versions(uint32_t bitmap)
|
||||||
{
|
{
|
||||||
|
assert_single_threaded();
|
||||||
allowed_versions &= bitmap;
|
allowed_versions &= bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,7 +17,12 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include "ovs-thread.h"
|
#include "ovs-thread.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
#include "poll-loop.h"
|
||||||
|
#include "socket-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef __CHECKER__
|
#ifdef __CHECKER__
|
||||||
@@ -26,6 +31,18 @@
|
|||||||
* cut-and-paste. Since "sparse" is just a checker, not a compiler, it
|
* cut-and-paste. Since "sparse" is just a checker, not a compiler, it
|
||||||
* doesn't matter that we don't define them. */
|
* doesn't matter that we don't define them. */
|
||||||
#else
|
#else
|
||||||
|
#include "vlog.h"
|
||||||
|
|
||||||
|
VLOG_DEFINE_THIS_MODULE(ovs_thread);
|
||||||
|
|
||||||
|
/* If there is a reason that we cannot fork anymore (unless the fork will be
|
||||||
|
* immediately followed by an exec), then this points to a string that
|
||||||
|
* explains why. */
|
||||||
|
static const char *must_not_fork;
|
||||||
|
|
||||||
|
/* True if we created any threads beyond the main initial thread. */
|
||||||
|
static bool multithreaded;
|
||||||
|
|
||||||
#define XPTHREAD_FUNC1(FUNCTION, PARAM1) \
|
#define XPTHREAD_FUNC1(FUNCTION, PARAM1) \
|
||||||
void \
|
void \
|
||||||
x##FUNCTION(PARAM1 arg1) \
|
x##FUNCTION(PARAM1 arg1) \
|
||||||
@@ -83,6 +100,9 @@ xpthread_create(pthread_t *threadp, pthread_attr_t *attr,
|
|||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
forbid_forking("multiple threads exist");
|
||||||
|
multithreaded = true;
|
||||||
|
|
||||||
error = pthread_create(threadp ? threadp : &thread, attr, start, arg);
|
error = pthread_create(threadp ? threadp : &thread, attr, start, arg);
|
||||||
if (error) {
|
if (error) {
|
||||||
ovs_abort(error, "pthread_create failed");
|
ovs_abort(error, "pthread_create failed");
|
||||||
@@ -106,4 +126,52 @@ ovsthread_once_done(struct ovsthread_once *once)
|
|||||||
atomic_store(&once->done, true);
|
atomic_store(&once->done, true);
|
||||||
xpthread_mutex_unlock(&once->mutex);
|
xpthread_mutex_unlock(&once->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Asserts that the process has not yet created any threads (beyond the initial
|
||||||
|
* thread). */
|
||||||
|
void
|
||||||
|
(assert_single_threaded)(const char *where)
|
||||||
|
{
|
||||||
|
if (multithreaded) {
|
||||||
|
VLOG_FATAL("%s: attempted operation not allowed when multithreaded",
|
||||||
|
where);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forks the current process (checking that this is allowed). Aborts with
|
||||||
|
* VLOG_FATAL if fork() returns an error, and otherwise returns the value
|
||||||
|
* returned by fork(). */
|
||||||
|
pid_t
|
||||||
|
(xfork)(const char *where)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
if (must_not_fork) {
|
||||||
|
VLOG_FATAL("%s: attempted to fork but forking not allowed (%s)",
|
||||||
|
where, must_not_fork);
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid < 0) {
|
||||||
|
VLOG_FATAL("fork failed (%s)", strerror(errno));
|
||||||
|
}
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Notes that the process must not call fork() from now on, for the specified
|
||||||
|
* 'reason'. (The process may still fork() if it execs itself immediately
|
||||||
|
* afterward.) */
|
||||||
|
void
|
||||||
|
forbid_forking(const char *reason)
|
||||||
|
{
|
||||||
|
ovs_assert(reason != NULL);
|
||||||
|
must_not_fork = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns true if the process is allowed to fork, false otherwise. */
|
||||||
|
bool
|
||||||
|
may_fork(void)
|
||||||
|
{
|
||||||
|
return !must_not_fork;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -18,6 +18,8 @@
|
|||||||
#define OVS_THREAD_H 1
|
#define OVS_THREAD_H 1
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include "ovs-atomic.h"
|
#include "ovs-atomic.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
@@ -365,5 +367,14 @@ ovsthread_once_start(struct ovsthread_once *once)
|
|||||||
#define ovsthread_once_start(ONCE) \
|
#define ovsthread_once_start(ONCE) \
|
||||||
((ONCE)->done ? false : ({ OVS_ACQUIRE(ONCE); true; }))
|
((ONCE)->done ? false : ({ OVS_ACQUIRE(ONCE); true; }))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void assert_single_threaded(const char *where);
|
||||||
|
#define assert_single_threaded() assert_single_threaded(SOURCE_LOCATOR)
|
||||||
|
|
||||||
|
pid_t xfork(const char *where);
|
||||||
|
#define xfork() xfork(SOURCE_LOCATOR)
|
||||||
|
|
||||||
|
void forbid_forking(const char *reason);
|
||||||
|
bool may_fork(void);
|
||||||
|
|
||||||
#endif /* ovs-thread.h */
|
#endif /* ovs-thread.h */
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "dynamic-string.h"
|
#include "dynamic-string.h"
|
||||||
#include "fatal-signal.h"
|
#include "fatal-signal.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "ovs-thread.h"
|
||||||
#include "poll-loop.h"
|
#include "poll-loop.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
#include "socket-util.h"
|
#include "socket-util.h"
|
||||||
@@ -71,6 +72,7 @@ process_init(void)
|
|||||||
static bool inited;
|
static bool inited;
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
|
assert_single_threaded();
|
||||||
if (inited) {
|
if (inited) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -180,6 +182,8 @@ process_start(char **argv, struct process **pp)
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
assert_single_threaded();
|
||||||
|
|
||||||
*pp = NULL;
|
*pp = NULL;
|
||||||
COVERAGE_INC(process_start);
|
COVERAGE_INC(process_start);
|
||||||
error = process_prestart(argv);
|
error = process_prestart(argv);
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include "fatal-signal.h"
|
#include "fatal-signal.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "hmap.h"
|
#include "hmap.h"
|
||||||
|
#include "ovs-thread.h"
|
||||||
#include "signals.h"
|
#include "signals.h"
|
||||||
#include "unixctl.h"
|
#include "unixctl.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@@ -297,6 +298,7 @@ time_alarm(unsigned int secs)
|
|||||||
long long int now;
|
long long int now;
|
||||||
long long int msecs;
|
long long int msecs;
|
||||||
|
|
||||||
|
assert_single_threaded();
|
||||||
time_init();
|
time_init();
|
||||||
time_refresh();
|
time_refresh();
|
||||||
|
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "byte-order.h"
|
#include "byte-order.h"
|
||||||
#include "coverage.h"
|
#include "coverage.h"
|
||||||
|
#include "ovs-thread.h"
|
||||||
#include "vlog.h"
|
#include "vlog.h"
|
||||||
|
|
||||||
VLOG_DEFINE_THIS_MODULE(util);
|
VLOG_DEFINE_THIS_MODULE(util);
|
||||||
@@ -339,6 +340,9 @@ set_program_name__(const char *argv0, const char *version, const char *date,
|
|||||||
const char *time)
|
const char *time)
|
||||||
{
|
{
|
||||||
const char *slash = strrchr(argv0, '/');
|
const char *slash = strrchr(argv0, '/');
|
||||||
|
|
||||||
|
assert_single_threaded();
|
||||||
|
|
||||||
program_name = slash ? slash + 1 : argv0;
|
program_name = slash ? slash + 1 : argv0;
|
||||||
|
|
||||||
free(program_version);
|
free(program_version);
|
||||||
|
Reference in New Issue
Block a user