1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <util/io/fd.h>
#include <util/io/fd_share.h>
#include <util/unittests/check_valgrind.h>
#include <util/unittests/fork.h>
#include <gtest/gtest.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstdio>
using namespace isc::util::io;
using namespace isc::util::unittests;
namespace {
// We test that we can transfer a pipe over other pipe
TEST(FDShare, transfer) {
if (!isc::util::unittests::runningOnValgrind()) {
// Get a pipe and fork
int pipes[2];
ASSERT_NE(-1, socketpair(AF_UNIX, SOCK_STREAM, 0, pipes));
const pid_t sender(fork());
ASSERT_NE(-1, sender);
if (sender) { // We are in parent
// Close the other side of pipe, we want only writable one
EXPECT_NE(-1, close(pipes[0]));
// Get a process to check data
int fd(0);
const pid_t checker(check_output(&fd, "data", 4));
ASSERT_NE(-1, checker);
// Now, send the file descriptor, close it and close the pipe
EXPECT_NE(-1, send_fd(pipes[1], fd));
EXPECT_NE(-1, close(pipes[1]));
EXPECT_NE(-1, close(fd));
// Check both subprocesses ended well
EXPECT_TRUE(process_ok(sender));
EXPECT_TRUE(process_ok(checker));
} else { // We are in child. We do not use ASSERT here
// Close the write end, we only read
if (close(pipes[1])) {
exit(1);
}
// Get the file descriptor
const int fd(recv_fd(pipes[0]));
if (fd == -1) {
exit(1);
}
// This pipe is not needed
if (close(pipes[0])) {
exit(1);
}
// Send "data" through the received fd, close it and be done
if (!write_data(fd, "data", 4) || close(fd) == -1) {
exit(1);
}
exit(0);
}
}
}
}
|