/*
* Copyright (c) 2008, 2009 Nicira Networks.
*
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
#include <config.h>
#include "fatal-signal.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include "shash.h"
#include "util.h"
+#define THIS_MODULE VLM_fatal_signal
+#include "vlog.h"
+
/* Signals to catch. */
static const int fatal_signals[] = { SIGTERM, SIGINT, SIGHUP, SIGALRM };
/* Registers 'hook' to be called when a process termination signal is raised.
* If 'run_at_exit' is true, 'hook' is also called during normal process
- * termination, e.g. when exit() is called or when main() returns. */
+ * termination, e.g. when exit() is called or when main() returns.
+ *
+ * 'func' will be invoked from an asynchronous signal handler, so it must be
+ * written appropriately. For example, it must not call most C library
+ * functions, including malloc() or free(). */
void
fatal_signal_add_hook(void (*func)(void *aux), void *aux, bool run_at_exit)
{
}
}
\f
-static char **files;
-static size_t n_files, max_files;
+static struct shash files = SHASH_INITIALIZER(&files);
static void unlink_files(void *aux);
static void do_unlink_files(void);
}
fatal_signal_block();
- if (n_files >= max_files) {
- files = x2nrealloc(files, &max_files, sizeof *files);
+ if (!shash_find(&files, file)) {
+ shash_add(&files, file, NULL);
}
- files[n_files++] = xstrdup(file);
fatal_signal_unblock();
}
void
fatal_signal_remove_file_to_unlink(const char *file)
{
- size_t i;
+ struct shash_node *node;
fatal_signal_block();
- for (i = 0; i < n_files; i++) {
- if (!strcmp(files[i], file)) {
- free(files[i]);
- files[i] = files[--n_files];
- break;
- }
+ node = shash_find(&files, file);
+ if (node) {
+ shash_delete(&files, node);
}
fatal_signal_unblock();
}
+/* Like fatal_signal_remove_file_to_unlink(), but also unlinks 'file'.
+ * Returns 0 if successful, otherwise a positive errno value. */
+int
+fatal_signal_unlink_file_now(const char *file)
+{
+ int error = unlink(file) ? errno : 0;
+ if (error) {
+ VLOG_WARN("could not unlink \"%s\" (%s)", file, strerror(error));
+ }
+
+ fatal_signal_remove_file_to_unlink(file);
+
+ return error;
+}
+
static void
unlink_files(void *aux UNUSED)
{
do_unlink_files();
}
+/* This is a fatal_signal_add_hook() callback (via unlink_files()). It will be
+ * invoked from an asynchronous signal handler, so it cannot call most C
+ * library functions (unlink() is an explicit exception, see
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html).
+ * That includes free(), so it doesn't try to free the 'files' data
+ * structure. */
static void
do_unlink_files(void)
{
- size_t i;
+ struct shash_node *node;
- for (i = 0; i < n_files; i++) {
- unlink(files[i]);
+ SHASH_FOR_EACH (node, &files) {
+ unlink(node->name);
}
}
\f