Kea  1.9.9-git
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 
9 #include <util/unittests/fork.h>
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 
22 using namespace isc::util::io;
23 
24 namespace {
25 
26 // Just a NOP function to ignore a signal but let it interrupt function.
27 void no_handler(int) { }
28 
29 };
30 
31 namespace isc {
32 namespace util {
33 namespace unittests {
34 
35 bool
36 process_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  */
66 pid_t
67 provide_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  */
94 pid_t
95 check_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.
Defines the logger used by the top-level component of kea-dhcp-ddns.
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
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
pid_t provide_input(int *read_pipe, const void *input, const size_t length)
Definition: fork.cc:67