E-MailRelay

gpidfile.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2024 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gpidfile.cpp
19///
20
21#include "gdef.h"
22#include "gpidfile.h"
23#include "gprocess.h"
24#include "groot.h"
25#include "gstr.h"
26#include "gcleanup.h"
27#include "gfile.h"
28#include "glog.h"
29#include <fstream>
30#include <string>
31
32 namespace G
33{
34 namespace PidFileImp
35 {
36 Process::Id read( SignalSafe , const char * path ) ;
37 bool cleanup( const Cleanup::Arg & ) noexcept ;
38 bool cleanup( const Path & ) noexcept ;
39 }
40}
41
42#ifndef G_LIB_SMALL
43 G::PidFile::PidFile()
44= default;
45#endif
46
47 G::PidFile::PidFile( const Path & path ) :
48 m_path((!path.empty()&&path.isRelative())?Path::join(Process::cwd(),path):path)
49{
50}
51
52 G::PidFile::~PidFile()
53{
54 static_assert( noexcept(m_path.cstr()) , "" ) ;
55 static_assert( noexcept(m_path.empty()) , "" ) ;
56 static_assert( noexcept(PidFileImp::cleanup(m_path)), "" ) ;
57 static_assert( noexcept(Root::atExit()) , "" ) ;
58 if( !m_path.empty() )
59 {
60 bool done = PidFileImp::cleanup( m_path ) ;
61 if( !done )
62 {
63 Root::atExit() ;
64 PidFileImp::cleanup( m_path ) ;
65 }
66 }
67}
68
69 void G::PidFile::mkdir()
70{
71 if( !m_path.empty() )
72 File::mkdir( m_path.dirname() , std::nothrow ) ;
73}
74
75 void G::PidFile::create( const Path & pid_file )
76{
77 if( !pid_file.empty() )
78 {
79 // (the effective user-id and umask is set by the caller)
80 std::ofstream file ;
81 File::open( file , pid_file , File::Text() ) ;
82 int e = G::Process::errno_() ;
83 if( !file.good() )
84 throw Error( "cannot create file" , pid_file.str() , G::Process::strerror(e) ) ;
85 Process::Id pid ;
86 file << pid.str() << std::endl ;
87 file.close() ;
88 if( file.fail() )
89 throw Error( "cannot write file" , pid_file.str() ) ;
90
91 Cleanup::add( PidFileImp::cleanup , Cleanup::arg(pid_file) ) ;
92 }
93}
94
95 void G::PidFile::commit()
96{
97 if( !m_path.empty() )
98 {
99 create( m_path ) ;
100 m_committed = true ;
101 }
102}
103
104 bool G::PidFile::committed() const
105{
106 return m_committed ;
107}
108
109 G::Path G::PidFile::path() const
110{
111 return m_path ;
112}
113
114// --
115
116 bool G::PidFileImp::cleanup( const Path & path ) noexcept
117{
118 try
119 {
120 int fd = File::open( path , File::InOutAppend::In ) ;
121 if( fd < 0 )
122 return false ;
123
124 constexpr std::size_t buffer_size = 11U ;
125 std::array<char,buffer_size> buffer {} ;
126 buffer[0U] = '\0' ;
127
128 ssize_t rc = File::read( fd , buffer.data() , buffer_size-1U ) ;
129 File::close( fd ) ;
130 if( rc <= 0 )
131 return false ;
132
133 Process::Id file_pid( buffer.data() , buffer.data()+static_cast<std::size_t>(rc) ) ;
134
135 Process::Id this_pid ;
136 if( this_pid != file_pid )
137 return false ; // not our pid file -- false => try again
138
139 return File::remove( path , std::nothrow ) ;
140 }
141 catch(...)
142 {
143 return false ;
144 }
145}
146
147 bool G::PidFileImp::cleanup( const Cleanup::Arg & arg ) noexcept
148{
149 try
150 {
151 return cleanup( Path(arg.str()) ) ;
152 }
153 catch(...)
154 {
155 return false ;
156 }
157}
158
G::Cleanup::arg
static Arg arg(const char *)
Duplicates a c-string for add().
Definition: gcleanup_unix.cpp:117
G::Cleanup::add
static void add(Fn, Arg arg)
Adds the given handler to the list of handlers that are to be called when the process terminates abno...
Definition: gcleanup_unix.cpp:94
G::File::Text
An overload discriminator for G::File::open().
Definition: gfile.h:64
G::File::open
static void open(std::ofstream &, const Path &)
Calls open() on the given output file stream.
Definition: gfile_unix.cpp:56
G::File::close
static void close(int fd) noexcept
Calls ::close() or equivalent.
Definition: gfile_unix.cpp:159
G::File::remove
static bool remove(const Path &path, std::nothrow_t) noexcept
Deletes the file or directory. Returns false on error.
Definition: gfile_unix.cpp:177
G::File::read
static ssize_t read(int fd, char *, std::size_t) noexcept
Calls read() or equivalent.
Definition: gfile_unix.cpp:149
G::File::mkdir
static bool mkdir(const Path &dir, std::nothrow_t)
Creates a directory.
Definition: gfile.cpp:235
G::Path
A Path object represents a file system path.
Definition: gpath.h:82
G::Path::str
std::string str() const
Returns the path string.
Definition: gpath.h:243
G::Path::empty
bool empty() const noexcept
Returns true if the path is empty.
Definition: gpath.h:237
G::PidFile::committed
bool committed() const
Returns true if commit() has been called with a valid path().
Definition: gpidfile.cpp:104
G::PidFile::commit
void commit()
Creates the pid file if a path has been defined.
Definition: gpidfile.cpp:95
G::PidFile::PidFile
PidFile()
Default constructor.
G::PidFile::~PidFile
~PidFile()
Destructor. Deletes the file.
Definition: gpidfile.cpp:52
G::PidFile::mkdir
void mkdir()
Creates the directory if it does not already exist.
Definition: gpidfile.cpp:69
G::PidFile::path
Path path() const
Returns the full path of the file.
Definition: gpidfile.cpp:109
G::Process::Id
Process-id class.
Definition: gprocess.h:167
G::Process
A static interface for doing things with processes.
Definition: gprocess.h:50
G::Process::strerror
static std::string strerror(int errno_)
Translates an 'errno' value into a meaningful diagnostic string.
Definition: gprocess_unix.cpp:142
G::Process::errno_
static int errno_(const SignalSafe &=G::SignalSafe()) noexcept
Returns the process's current 'errno' value.
Definition: gprocess_unix.cpp:125
G::Root::atExit
static void atExit() noexcept
Re-acquires special privileges just before process exit.
Definition: groot.cpp:68
gcleanup.h
gfile.h
glog.h
gpidfile.h
gprocess.h
groot.h
gstr.h
G
Low-level classes.
Definition: garg.h:36