Kea 2.7.6
fork.cc
Go to the documentation of this file.
1// Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
10
11#include <util/io/fd.h>
12
13#include <sys/types.h>
14#include <sys/wait.h>
15#include <unistd.h>
16#include <signal.h>
17#include <string.h>
18#include <cerrno>
19#include <stdlib.h>
20#include <stdio.h>
21
22using namespace isc::util::io;
23
24namespace {
25
26// Just a NOP function to ignore a signal but let it interrupt function.
27void no_handler(int) { }
28
29};
30
31namespace isc {
32namespace util {
33namespace unittests {
34
35bool
36process_ok(pid_t process) {
37 // Create a timeout
38 struct sigaction ignored, original;
39 memset(&ignored, 0, sizeof ignored);
40 ignored.sa_handler = no_handler;
41 if (sigaction(SIGALRM, &ignored, &original)) {
42 return false;
43 }
44 // It is long, but if everything is OK, it'll not happen
45 alarm(10);
46 int status;
47 int result(waitpid(process, &status, 0) == -1);
48 // Cancel the alarm and return the original handler
49 alarm(0);
50 if (sigaction(SIGALRM, &original, NULL)) {
51 return false;
52 }
53 // Check what we found out
54 if (result) {
55 if (errno == EINTR)
56 kill(process, SIGTERM);
57 return false;
58 }
59 return WIFEXITED(status) && WEXITSTATUS(status) == 0;
60}
61
62/*
63 * This creates a pipe, forks and feeds the pipe with given data.
64 * Used to provide the input in non-blocking/asynchronous way.
65 */
66pid_t
67provide_input(int *read_pipe, const void *input, const size_t length)
68{
69 int pipes[2];
70 if (pipe(pipes)) {
71 return -1;
72 }
73 *read_pipe = pipes[0];
74
75 pid_t pid(fork());
76 if (pid) { // We are in the parent
77 return pid;
78 } else { // This is in the child, just puts the data there
79 close(pipes[0]);
80 if (!write_data(pipes[1], input, length)) {
81 exit(1);
82 } else {
83 close(pipes[1]);
84 exit(0);
85 }
86 }
87}
88
89
90/*
91 * This creates a pipe, forks and reads the pipe and compares it
92 * with given data. Used to check output of run in an asynchronous way.
93 */
94pid_t
95check_output(int *write_pipe, const void* const output, const size_t length)
96{
97 int pipes[2];
98 if (pipe(pipes)) {
99 return -1;
100 }
101 *write_pipe = pipes[1];
102 pid_t pid(fork());
103 if (pid) { // We are in parent
104 close(pipes[0]);
105 return pid;
106 } else {
107 close(pipes[1]);
108 unsigned char* buffer = new unsigned char[length + 1];
109 // Try to read one byte more to see if the output ends here
110 size_t got_length(read_data(pipes[0], buffer, length + 1));
111 bool ok(true);
112 if (got_length != length) {
113 fprintf(stderr, "Different length (expected %u, got %u)\n",
114 static_cast<unsigned>(length),
115 static_cast<unsigned>(got_length));
116 ok = false;
117 }
118 if(!ok || memcmp(buffer, output, length)) {
119 const unsigned char *output_c(static_cast<const unsigned char *>(
120 output));
121 // If they differ, print what we have
122 for(size_t i(0); i != got_length; ++ i) {
123 fprintf(stderr, "%02hhx", buffer[i]);
124 }
125 fprintf(stderr, "\n");
126 for(size_t i(0); i != length; ++ i) {
127 fprintf(stderr, "%02hhx", output_c[i]);
128 }
129 fprintf(stderr, "\n");
130 delete [] buffer;
131 exit(1);
132 } else {
133 delete [] buffer;
134 exit(0);
135 }
136 }
137}
138
139}
140}
141}
Wrappers around common unix fd manipulation functions.
Help functions to fork the test case process.
ssize_t read_data(const int fd, void *buffer_v, const size_t length)
Definition fd.cc:50
bool write_data(const int fd, const void *buffer_v, const size_t length)
Definition fd.cc:19
pid_t provide_input(int *read_pipe, const void *input, const size_t length)
Definition fork.cc:67
bool process_ok(pid_t process)
Checks that a process terminates correctly.
Definition fork.cc:36
pid_t check_output(int *write_pipe, const void *const output, const size_t length)
Definition fork.cc:95
Defines the logger used by the top-level component of kea-lfc.