This is useful when we're opening up to fork off child processes,
to avoid various sockets etc. leaking into them (without having to
close all of them explicitly).
12 files changed:
#include <assert.h>
#include <errno.h>
#include <assert.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <poll.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <poll.h>
// NOTE: We set as non-blocking, so the acceptor thread can notice that we want to shut it down.
int server_sock;
if (socket_type == TCP_SOCKET) {
// NOTE: We set as non-blocking, so the acceptor thread can notice that we want to shut it down.
int server_sock;
if (socket_type == TCP_SOCKET) {
- server_sock = socket(PF_INET6, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
+ server_sock = socket(PF_INET6, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
} else {
assert(socket_type == UDP_SOCKET);
} else {
assert(socket_type == UDP_SOCKET);
- server_sock = socket(PF_INET6, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
+ server_sock = socket(PF_INET6, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_UDP);
}
if (server_sock == -1) {
log_perror("socket");
}
if (server_sock == -1) {
log_perror("socket");
certificate_chain(serialized.certificate_chain()),
private_key(serialized.private_key())
{
certificate_chain(serialized.certificate_chain()),
private_key(serialized.private_key())
{
+ // Set back the close-on-exec flag for the socket.
+ // (This can't leak into a child, since we haven't been started yet.)
+ fcntl(server_sock, F_SETFD, 1);
}
AcceptorProto Acceptor::serialize() const
{
}
AcceptorProto Acceptor::serialize() const
{
+ // Unset the close-on-exec flag for the socket.
+ // (This can't leak into a child, since there's only one thread left.)
+ fcntl(server_sock, F_SETFD, 0);
+
char buf[INET6_ADDRSTRLEN];
inet_ntop(addr.sin6_family, &addr.sin6_addr, buf, sizeof(buf));
char buf[INET6_ADDRSTRLEN];
inet_ntop(addr.sin6_family, &addr.sin6_addr, buf, sizeof(buf));
socklen_t addrlen = sizeof(addr);
// Get a new socket, and set it as nonblocking.
socklen_t addrlen = sizeof(addr);
// Get a new socket, and set it as nonblocking.
- int sock = accept4(server_sock, reinterpret_cast<sockaddr *>(&addr), &addrlen, SOCK_NONBLOCK);
+ int sock = accept4(server_sock, reinterpret_cast<sockaddr *>(&addr), &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
if (sock == -1 && errno == EINTR) {
continue;
}
if (sock == -1 && errno == EINTR) {
continue;
}
if (filename.empty()) {
logfp = nullptr;
} else {
if (filename.empty()) {
logfp = nullptr;
} else {
- logfp = fopen(filename.c_str(), "a+");
+ logfp = fopen(filename.c_str(), "a+e");
if (logfp == nullptr) {
log_perror(filename.c_str());
// Continue as before.
if (logfp == nullptr) {
log_perror(filename.c_str());
// Continue as before.
#include <stdio.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdint.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdint.h>
#include <sys/socket.h>
#include "client.h"
#include "log.h"
#include "client.h"
#include "log.h"
bytes_lost(serialized.bytes_lost()),
num_loss_events(serialized.num_loss_events())
{
bytes_lost(serialized.bytes_lost()),
num_loss_events(serialized.num_loss_events())
{
+ // Set back the close-on-exec flag for the socket.
+ // (This can't leak into a child, since we haven't been started yet.)
+ fcntl(sock, F_SETFD, 1);
+
if (stream != nullptr) {
if (setsockopt(sock, SOL_SOCKET, SO_MAX_PACING_RATE, &stream->pacing_rate, sizeof(stream->pacing_rate)) == -1) {
if (stream->pacing_rate != ~0U) {
if (stream != nullptr) {
if (setsockopt(sock, SOL_SOCKET, SO_MAX_PACING_RATE, &stream->pacing_rate, sizeof(stream->pacing_rate)) == -1) {
if (stream->pacing_rate != ~0U) {
ClientProto Client::serialize(unordered_map<const string *, size_t> *short_response_pool) const
{
ClientProto Client::serialize(unordered_map<const string *, size_t> *short_response_pool) const
{
+ // Unset the close-on-exec flag for the socket.
+ // (This can't leak into a child, since there's only one thread left.)
+ fcntl(sock, F_SETFD, 0);
+
ClientProto serialized;
serialized.set_sock(sock);
serialized.set_remote_addr(remote_addr);
ClientProto serialized;
serialized.set_sock(sock);
serialized.set_remote_addr(remote_addr);
#include <assert.h>
#include <errno.h>
#include <assert.h>
#include <errno.h>
#include <math.h>
#include <netdb.h>
#include <netinet/in.h>
#include <math.h>
#include <netdb.h>
#include <netinet/in.h>
has_metacube_header(serialized.has_metacube_header()),
sock(serialized.sock())
{
has_metacube_header(serialized.has_metacube_header()),
sock(serialized.sock())
{
+ // Set back the close-on-exec flag for the socket.
+ // (This can't leak into a child, since we haven't been started yet.)
+ fcntl(sock, F_SETFD, 1);
+
pending_data.resize(serialized.pending_data().size());
memcpy(&pending_data[0], serialized.pending_data().data(), serialized.pending_data().size());
pending_data.resize(serialized.pending_data().size());
memcpy(&pending_data[0], serialized.pending_data().data(), serialized.pending_data().size());
InputProto HTTPInput::serialize() const
{
InputProto HTTPInput::serialize() const
{
+ // Unset the close-on-exec flag for the socket.
+ // (This can't leak into a child, since there's only one thread left.)
+ fcntl(sock, F_SETFD, 0);
+
InputProto serialized;
serialized.set_state(state);
serialized.set_url(url);
InputProto serialized;
serialized.set_state(state);
serialized.set_url(url);
for ( ; ai && !should_stop(); ai = ai->ai_next) {
// Now do a non-blocking connect. This is important because we want to be able to be
// woken up, even though it's rather cumbersome.
for ( ; ai && !should_stop(); ai = ai->ai_next) {
// Now do a non-blocking connect. This is important because we want to be able to be
// woken up, even though it's rather cumbersome.
- int sock = socket(ai->ai_family, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
+ int sock = socket(ai->ai_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, IPPROTO_TCP);
if (sock == -1) {
// Could be e.g. EPROTONOSUPPORT. The show must go on.
continue;
if (sock == -1) {
// Could be e.g. EPROTONOSUPPORT. The show must go on.
continue;
// Open a new, temporary file.
char *filename = strdup((stats_file + ".new.XXXXXX").c_str());
// Open a new, temporary file.
char *filename = strdup((stats_file + ".new.XXXXXX").c_str());
- fd = mkostemp(filename, O_WRONLY);
+ fd = mkostemp(filename, O_WRONLY | O_CLOEXEC);
if (fd == -1) {
log_perror(filename);
free(filename);
if (fd == -1) {
log_perror(filename);
free(filename);
#include <assert.h>
#include <errno.h>
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <string>
#include <vector>
#include <string>
#include <vector>
void add_log_destination_file(const string &filename)
{
void add_log_destination_file(const string &filename)
{
- FILE *fp = fopen(filename.c_str(), "a");
+ FILE *fp = fopen(filename.c_str(), "ae");
if (fp == nullptr) {
perror(filename.c_str());
return;
if (fp == nullptr) {
perror(filename.c_str());
return;
#include <assert.h>
#include <errno.h>
#include <assert.h>
#include <errno.h>
#include <getopt.h>
#include <limits.h>
#include <signal.h>
#include <getopt.h>
#include <limits.h>
#include <signal.h>
char buf[16];
sprintf(buf, "%d", state_fd);
char buf[16];
sprintf(buf, "%d", state_fd);
+ // Unset the close-on-exec flag for the state fd.
+ // (This can't leak into a child, since there's only one thread left.)
+ fcntl(state_fd, F_SETFD, 0);
+
for ( ;; ) {
execlp(argv0_canon, argv0_canon, config_filename_canon, "--state", buf, nullptr);
open_logs(config.log_destinations);
for ( ;; ) {
execlp(argv0_canon, argv0_canon, config_filename_canon, "--state", buf, nullptr);
open_logs(config.log_destinations);
- epoll_fd = epoll_create(1024); // Size argument is ignored.
+ epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (epoll_fd == -1) {
log_perror("epoll_fd");
exit(1);
if (epoll_fd == -1) {
log_perror("epoll_fd");
exit(1);
// Open a new, temporary file.
filename = strdup((stats_file + ".new.XXXXXX").c_str());
// Open a new, temporary file.
filename = strdup((stats_file + ".new.XXXXXX").c_str());
- fd = mkostemp(filename, O_WRONLY);
+ fd = mkostemp(filename, O_WRONLY | O_CLOEXEC);
if (fd == -1) {
log_perror(filename);
free(filename);
if (fd == -1) {
log_perror(filename);
free(filename);
#include <assert.h>
#include <errno.h>
#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <stddef.h>
#include <stdlib.h>
#include <poll.h>
#include <stddef.h>
#include <stdlib.h>
: url(serialized.url()),
sock(serialized.sock())
{
: url(serialized.url()),
sock(serialized.sock())
{
+ // Set back the close-on-exec flag for the socket.
+ // (This can't leak into a child, since we haven't been started yet.)
+ fcntl(sock, F_SETFD, 1);
+
// Should be verified by the caller.
string protocol;
bool ok = parse_url(url, &protocol, &user, &host, &port, &path);
// Should be verified by the caller.
string protocol;
bool ok = parse_url(url, &protocol, &user, &host, &port, &path);
InputProto UDPInput::serialize() const
{
InputProto UDPInput::serialize() const
{
+ // Unset the close-on-exec flag for the socket.
+ // (This can't leak into a child, since there's only one thread left.)
+ fcntl(sock, F_SETFD, 0);
+
InputProto serialized;
serialized.set_url(url);
serialized.set_sock(sock);
InputProto serialized;
serialized.set_url(url);
serialized.set_sock(sock);
UDPStream::UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate, int ttl, int multicast_iface_index)
: dst(dst)
{
UDPStream::UDPStream(const sockaddr_in6 &dst, uint32_t pacing_rate, int ttl, int multicast_iface_index)
: dst(dst)
{
- sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ sock = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
if (sock == -1) {
// Oops. Ignore this output, then.
log_perror("socket");
if (sock == -1) {
// Oops. Ignore this output, then.
log_perror("socket");
int make_tempfile(const string &contents)
{
int make_tempfile(const string &contents)
{
- int fd = open("/tmp", O_RDWR | O_TMPFILE, 0600);
+ int fd = open("/tmp", O_RDWR | O_TMPFILE | O_CLOEXEC, 0600);
if (fd == -1) {
char filename[] = "/tmp/cubemap.XXXXXX";
mode_t old_umask = umask(077);
if (fd == -1) {
char filename[] = "/tmp/cubemap.XXXXXX";
mode_t old_umask = umask(077);