argv += optind;
/* Make sure that the ezio3 terminfo entry is available. */
- dummy_fd = open("/dev/null", O_RDWR);
+ dummy_fd = get_null_fd();
if (dummy_fd >= 0) {
if (setupterm("ezio3", dummy_fd, &retval) == ERR) {
if (retval == 0) {
}
}
del_curterm(cur_term);
- close(dummy_fd);
- } else {
- ovs_error(errno, "failed to open /dev/null");
}
/* Lock serial port. */
unblock_sigchld(&oldsigs);
for (fd = 0; fd < fd_max; fd++) {
if (is_member(fd, null_fds, n_null_fds)) {
+ /* We can't use get_null_fd() here because we might have
+ * already closed its fd. */
int nullfd = open("/dev/null", O_RDWR);
dup2(nullfd, fd);
close(nullfd);
: htonl(0)); /* ??? */
}
+/* Returns a readable and writable fd for /dev/null, if successful, otherwise
+ * a negative errno value. The caller must not close the returned fd (because
+ * the same fd will be handed out to subsequent callers). */
+int
+get_null_fd(void)
+{
+ static int null_fd = -1;
+ if (null_fd < 0) {
+ null_fd = open("/dev/null", O_RDWR);
+ if (null_fd < 0) {
+ int error = errno;
+ VLOG_ERR("could not open /dev/null: %s", strerror(error));
+ return -error;
+ }
+ }
+ return null_fd;
+}
+
int
read_fully(int fd, void *p_, size_t size, size_t *bytes_read)
{
const char *bind_path, const char *connect_path);
int get_unix_name_len(socklen_t sun_len);
uint32_t guess_netmask(uint32_t ip);
+int get_null_fd(void);
int read_fully(int fd, void *, size_t, size_t *bytes_read);
int write_fully(int fd, const void *, size_t, size_t *bytes_written);
};
/* File descriptors for waking up when a child dies. */
-static int signal_fds[2];
-
-/* File descriptor for /dev/null. */
-static int null_fd = -1;
+static int signal_fds[2] = {-1, -1};
static void send_child_status(struct rconn *, uint32_t xid, uint32_t status,
const void *data, size_t size);
* subprocesses at once? Would also want to catch fatal signals and
* kill them at the same time though. */
fatal_signal_fork();
- dup2(null_fd, 0);
+ dup2(get_null_fd(), 0);
dup2(output_fds[1], 1);
- dup2(null_fd, 2);
+ dup2(get_null_fd(), 2);
max_fds = get_max_fds();
for (i = 3; i < max_fds; i++) {
close(i);
struct sigaction sa;
*executerp = NULL;
- if (null_fd == -1) {
+ if (signal_fds[0] == -1) {
+ /* Make sure we can get a fd for /dev/null. */
+ int null_fd = get_null_fd();
+ if (null_fd < 0) {
+ return -null_fd;
+ }
+
/* Create pipe for notifying us that SIGCHLD was invoked. */
if (pipe(signal_fds)) {
VLOG_ERR("pipe failed: %s", strerror(errno));
}
set_nonblocking(signal_fds[0]);
set_nonblocking(signal_fds[1]);
-
- /* Open /dev/null. */
- null_fd = open("/dev/null", O_RDWR);
- if (null_fd < 0) {
- int error = errno;
- VLOG_ERR("could not open /dev/null: %s", strerror(error));
- close(signal_fds[0]);
- close(signal_fds[1]);
- return error;
- }
}
/* Set up signal handler. */