Return NULL thread local storage instead of raising exception
[libi2ncommon] / src / pidfile.cpp
1 /*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
13
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
16
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
19 */
20 /**
21    Pid file handling
22
23    @copyright Intra2net AG
24 */
25 #include "pidfile.hpp"
26 #include <sys/types.h>
27
28 #include <signal.h>
29 #include <fstream>
30 #include <sstream>
31 #include <iostream>
32 #include <stdexcept>
33
34 #include "filefunc.hxx"
35 #include <unistd.h>
36
37 using namespace std;
38 using namespace I2n;
39
40 /**
41  * Constructor.
42  * @param filename Full path to the pid file
43  * @param remove_file_on_destruction Remove pid file on destruction of the object. Only useful if running as root.
44  */
45 PidFile::PidFile(const std::string &filename, bool remove_file_on_destruction)
46 {
47    Filename = filename;
48    RemoveFileOnDestruction = remove_file_on_destruction;
49    WroteFile = false;
50 }
51
52 /**
53  * Destructor. We delete the pid file if #RemoveFileOnDestruction is set
54  * and we actually wrote a file (#WroteFile).
55  * This is only possible if we run with root priviledges as /var/run
56  * is root writable only.
57  */
58 PidFile::~PidFile()
59 {
60    if (RemoveFileOnDestruction && WroteFile)
61       unlink(Filename);
62 }
63
64 /**
65  * Checks if the pid file for this program already exists.
66  * If yes it does a "kill" probe to see if it is alive.
67  * @param running_pid[out] Store pid number of instance if already running
68  * @return true if running, false otherweise
69  */
70 bool PidFile::check_already_running(pid_t *running_pid)
71 {
72    // Check if there is an existing pid file
73    ifstream in(Filename.c_str());
74    if (!in)
75       return false;
76
77    pid_t read_pid = 0;
78    if (!(in >> read_pid))
79       return false;
80
81    // Ok, we got an existing pid file.
82    // Check if program is still alive
83    if (kill(read_pid, 0) == 0)
84    {
85       if (running_pid)
86          *running_pid = read_pid;
87
88       // State: running
89       return true;
90    }
91
92    // Default state: not running
93    return false;
94 }
95
96 /**
97  * Write pid file
98  * @return true if file was written, false otherwise
99  */
100 bool PidFile::write()
101 {
102    ofstream out(Filename.c_str());
103    if (!out)
104       return false;
105
106    out << getpid() << endl;
107
108    WroteFile = true;
109
110    return true;
111 }