#include <assert.h>
#include <errno.h>
+#include <fcntl.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) {
- 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);
- 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");
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
{
+ // 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));
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 (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.
#include <stdio.h>
#include <arpa/inet.h>
+#include <fcntl.h>
#include <netinet/in.h>
#include <stdint.h>
#include <sys/socket.h>
+#include <unistd.h>
#include "client.h"
#include "log.h"
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) {
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);
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <math.h>
#include <netdb.h>
#include <netinet/in.h>
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());
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);
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;
// 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);
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
+#include <unistd.h>
#include <string>
#include <vector>
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;
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <signal.h>
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);
Server::Server()
{
- 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);
// 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);
#include <assert.h>
#include <errno.h>
+#include <fcntl.h>
#include <poll.h>
#include <stddef.h>
#include <stdlib.h>
: 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);
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);
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");
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);