Electroneum
Toggle main menu visibility
Loading...
Searching...
No Matches
posix_fork.cpp
Go to the documentation of this file.
1
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
2
//
3
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
//
6
7
#include "
daemonizer/posix_fork.h
"
8
#include "
misc_log_ex.h
"
9
10
#include <cstdlib>
11
#include <fcntl.h>
12
#include <unistd.h>
13
#include <stdexcept>
14
#include <string>
15
16
#ifndef TMPDIR
17
#define TMPDIR "/tmp"
18
#endif
19
20
namespace
posix
{
21
22
namespace
{
23
void
quit(
const
std::string &
message
)
24
{
25
LOG_ERROR
(
message
);
26
throw
std::runtime_error(
message
);
27
}
28
}
29
30
void
fork
(
const
std::string & pidfile)
31
{
32
// If a PID file is specified, we open the file here, because
33
// we can't report errors after the fork operation.
34
// When we fork, we close thise file in each of the parent
35
// processes.
36
// Only in the final child process do we write the PID to the
37
// file (and close it).
38
std::ofstream pidofs;
39
if
(! pidfile.empty ())
40
{
41
int
oldpid;
42
std::ifstream pidrifs;
43
pidrifs.open(pidfile, std::fstream::in);
44
if
(! pidrifs.fail())
45
{
46
// Read the PID and send signal 0 to see if the process exists.
47
if
(pidrifs >> oldpid && oldpid > 1 && kill(oldpid, 0) == 0)
48
{
49
quit(
"PID file "
+ pidfile +
" already exists and the PID therein is valid"
);
50
}
51
pidrifs.close();
52
}
53
54
pidofs.open(pidfile, std::fstream::out | std::fstream::trunc);
55
if
(pidofs.fail())
56
{
57
quit(
"Failed to open specified PID file for writing"
);
58
}
59
}
60
// Fork the process and have the parent exit. If the process was started
61
// from a shell, this returns control to the user. Forking a new process is
62
// also a prerequisite for the subsequent call to setsid().
63
if
(pid_t pid =
::fork
())
64
{
65
if
(pid > 0)
66
{
67
// We're in the parent process and need to exit.
68
pidofs.close();
69
// When the exit() function is used, the program terminates without
70
// invoking local variables' destructors. Only global variables are
71
// destroyed.
72
exit(0);
73
}
74
else
75
{
76
quit(
"First fork failed"
);
77
}
78
}
79
80
// Make the process a new session leader. This detaches it from the
81
// terminal.
82
setsid();
83
84
// A second fork ensures the process cannot acquire a controlling terminal.
85
if
(pid_t pid =
::fork
())
86
{
87
if
(pid > 0)
88
{
89
pidofs.close();
90
exit(0);
91
}
92
else
93
{
94
quit(
"Second fork failed"
);
95
}
96
}
97
98
if
(! pidofs.fail())
99
{
100
int
pid = ::getpid();
101
pidofs << pid << std::endl;
102
pidofs.close();
103
}
104
105
// Close the standard streams. This decouples the daemon from the terminal
106
// that started it.
107
close(0);
108
close(1);
109
close(2);
110
111
// We don't want the daemon to have any standard input.
112
if
(open(
"/dev/null"
, O_RDONLY) < 0)
113
{
114
quit(
"Unable to open /dev/null"
);
115
}
116
117
#ifdef DEBUG_TMPDIR_LOG
118
// Send standard output to a log file.
119
const
char
*tmpdir = getenv(
"TMPDIR"
);
120
if
(!tmpdir)
121
tmpdir =
TMPDIR
;
122
std::string output = tmpdir;
123
output +=
"/electroneum.daemon.stdout.stderr"
;
124
const
int
flags = O_WRONLY | O_CREAT | O_APPEND;
125
const
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
126
if
(open(output.c_str(), flags, mode) < 0)
127
{
128
quit(
"Unable to open output file: "
+ output);
129
}
130
131
// Also send standard error to the same log file.
132
if
(dup(1) < 0)
133
{
134
quit(
"Unable to dup output descriptor"
);
135
}
136
#endif
137
}
138
139
}
// namespace posix
message
std::string message("Message requiring signing")
misc_log_ex.h
LOG_ERROR
#define LOG_ERROR(x)
Definition
misc_log_ex.h:98
posix
Definition
posix_fork.cpp:20
posix::fork
void fork(const std::string &pidfile)
Definition
posix_fork.cpp:30
TMPDIR
#define TMPDIR
Definition
posix_fork.cpp:17
posix_fork.h
src
daemonizer
posix_fork.cpp
Generated on
for Electroneum by
1.17.0