mirror of
https://git.freebsd.org/src.git
synced 2026-01-16 23:02:24 +00:00
libutil++: Add freebsd::pidfile wrapper class around struct pidfh
This class wraps the pidfile_* API from libutil. The destructor calls pidfile_remove() when an object is destroyed. This class is similar to std::unique_ptr<> in that it retains exclusive ownership of the pidfh object. In addition to release and reset methods, write, close, and fileno methods are provided as wrappers for pidfile_*. Sponsored by: Chelsio Communications Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
This commit is contained in:
parent
2bb9180bb5
commit
7be913e00d
5 changed files with 232 additions and 0 deletions
|
|
@ -9,6 +9,7 @@ MAN+= freebsd::FILE_up.3 \
|
|||
freebsd::fd_up.3 \
|
||||
freebsd::malloc_up.3 \
|
||||
freebsd::nvlist_up.3 \
|
||||
freebsd::pidfile.3 \
|
||||
freebsd::stringf.3
|
||||
|
||||
.include <src.opts.mk>
|
||||
|
|
|
|||
110
lib/libutil++/freebsd::pidfile.3
Normal file
110
lib/libutil++/freebsd::pidfile.3
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
.\"
|
||||
.\" SPDX-License-Identifier: BSD-2-Clause
|
||||
.\"
|
||||
.\" Copyright (c) 2025 Chelsio Communications, Inc.
|
||||
.\" Written by: John Baldwin <jhb@FreeBSD.org>
|
||||
.\"
|
||||
.Dd July 31, 2025
|
||||
.Dt FREEBSD::STRINGF 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm freebsd::pidfile
|
||||
.Nd own a PID file handle
|
||||
.Sh LIBRARY
|
||||
.Lb libutil++
|
||||
.Sh SYNOPSIS
|
||||
.In libutil++.hh
|
||||
.Pp
|
||||
.Vt class freebsd::pidfile
|
||||
{
|
||||
.Bd -ragged -offset indent
|
||||
.Fn pidfile
|
||||
.Fn pidfile "struct pidfh *pfh"
|
||||
.Fn pidfile "pidfile &&other"
|
||||
.Fn ~pidfile
|
||||
.Ft struct pidfh *
|
||||
.Fn release
|
||||
.Ft void
|
||||
.Fn reset "struct pidfh *newpfh = nullptr"
|
||||
.Ft int
|
||||
.Fn write
|
||||
.Ft int
|
||||
.Fn close
|
||||
.Ft int
|
||||
.Fn fileno
|
||||
.Ft "pidfile &"
|
||||
.Fn operator= "pidfile &&other"
|
||||
.Ft "pidfile &"
|
||||
.Fn operator= "struct pidfh *pfh"
|
||||
.Fn "explicit operator bool"
|
||||
.Ed
|
||||
};
|
||||
.Sh DESCRIPTION
|
||||
Each instance of this class owns a PID file handle created by
|
||||
.Xr pidfile_open 3 .
|
||||
This class is patterned on std::unique_ptr;
|
||||
however,
|
||||
rather than exporting the raw pointer via a
|
||||
.Fn get
|
||||
method,
|
||||
this class provides wrapper methods for each of the other
|
||||
.Xr pidfile 3
|
||||
functions.
|
||||
The currently-owned PID file is removed by invoking
|
||||
.Xr pidfile_remove 3
|
||||
when an instance of this class is destroyed.
|
||||
The currently-owned PID file is also removed if it is replaced by the
|
||||
.Fn reset
|
||||
method or assignment operators.
|
||||
.Pp
|
||||
The
|
||||
.Fn release
|
||||
method relinquishes ownership of the current PID file handle and returns the
|
||||
value of the previously-owned PID file handle.
|
||||
.Pp
|
||||
The
|
||||
.Fn write
|
||||
method writes out the PID of the current process to the PID file via
|
||||
.Xr pidfile_write 3 .
|
||||
.Pp
|
||||
The
|
||||
.Fn close
|
||||
method closes the current PID file without removing it via
|
||||
.Xr pidfile_close 3 .
|
||||
If the close succeeds, the PID file handle is no longer valid.
|
||||
.Pp
|
||||
The
|
||||
.Fn fileno
|
||||
method returns the underlying file descriptor for the current PID file via
|
||||
.Xr pidfile_fileno 3 .
|
||||
.Pp
|
||||
The explicit
|
||||
.Vt bool
|
||||
conversion operator permits testing the validity of an object.
|
||||
The operator returns true if the instance owns a valid PID file handle.
|
||||
.Sh EXAMPLES
|
||||
.Bd -literal -offset indent
|
||||
int
|
||||
main()
|
||||
{
|
||||
freebsd::pidfile pf(pidfile_open("/var/run/daemon.pid",
|
||||
0600, NULL));
|
||||
if (!pf)
|
||||
err(1, "pidfile_open");
|
||||
|
||||
if (daemon(0, 0) == -1) {
|
||||
warn("daemon");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pf->write();
|
||||
|
||||
for (;;) {
|
||||
/* Do Work */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr pidfile 3
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
#define __LIBUTILPP_HH__
|
||||
|
||||
#include <sys/nv.h>
|
||||
#include <libutil.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
@ -145,6 +146,79 @@ namespace freebsd {
|
|||
|
||||
using nvlist_up = std::unique_ptr<nvlist_t, nvlist_deleter>;
|
||||
|
||||
/*
|
||||
* A wrapper class for the pidfile_* API. The destructor
|
||||
* calls pidfile_remove() when an object is destroyed. This
|
||||
* class is similar to std::unique_ptr<> in that it retains
|
||||
* exclusive ownership of the pidfh object.
|
||||
*
|
||||
* In addition to release() and reset methods(), write(),
|
||||
* close(), and fileno() methods are provided as wrappers for
|
||||
* pidfile_*.
|
||||
*/
|
||||
class pidfile {
|
||||
public:
|
||||
pidfile() = default;
|
||||
pidfile(struct pidfh *pfh) : pfh(pfh) {}
|
||||
pidfile(pidfile &&other) : pfh(other.release()) {}
|
||||
pidfile(pidfile const &) = delete;
|
||||
|
||||
~pidfile() { reset(); }
|
||||
|
||||
struct pidfh *release()
|
||||
{
|
||||
struct pidfh *oldpfh = pfh;
|
||||
|
||||
pfh = nullptr;
|
||||
return (oldpfh);
|
||||
}
|
||||
|
||||
void reset(struct pidfh *newpfh = nullptr)
|
||||
{
|
||||
if (pfh != nullptr)
|
||||
pidfile_remove(pfh);
|
||||
pfh = newpfh;
|
||||
}
|
||||
|
||||
int write()
|
||||
{
|
||||
return (pidfile_write(pfh));
|
||||
}
|
||||
|
||||
int close()
|
||||
{
|
||||
int rv = pidfile_close(pfh);
|
||||
if (rv == 0)
|
||||
pfh = nullptr;
|
||||
return (rv);
|
||||
}
|
||||
|
||||
int fileno()
|
||||
{
|
||||
return (pidfile_fileno(pfh));
|
||||
}
|
||||
|
||||
pidfile &operator=(pidfile &&other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
reset(other.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
pidfile &operator=(pidfile const &) = delete;
|
||||
|
||||
pidfile &operator=(struct pidfh *newpfh)
|
||||
{
|
||||
reset(newpfh);
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return pfh != nullptr; }
|
||||
private:
|
||||
struct pidfh *pfh = nullptr;
|
||||
};
|
||||
|
||||
/*
|
||||
* Returns a std::string containing the same output as
|
||||
* sprintf(). Throws std::bad_alloc if an error occurs.
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
PACKAGE= tests
|
||||
|
||||
ATF_TESTS_CXX+= pidfile_test
|
||||
ATF_TESTS_CXX+= stringf_test
|
||||
ATF_TESTS_CXX+= up_test
|
||||
|
||||
CFLAGS+= -I${SRCTOP}/lib/libutil++
|
||||
LIBADD+= util++
|
||||
|
||||
LIBADD.pidfile_test+= util
|
||||
|
||||
.include <bsd.test.mk>
|
||||
|
|
|
|||
44
lib/libutil++/tests/pidfile_test.cc
Normal file
44
lib/libutil++/tests/pidfile_test.cc
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2025 Chelsio Communications, Inc.
|
||||
* Written by: John Baldwin <jhb@FreeBSD.org>
|
||||
*/
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
#include <sys/stat.h>
|
||||
#include <libutil.h>
|
||||
|
||||
#include <libutil++.hh>
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(basic);
|
||||
ATF_TEST_CASE_BODY(basic)
|
||||
{
|
||||
pid_t other;
|
||||
struct pidfh *pfh = pidfile_open("test_pidfile", 0600, &other);
|
||||
ATF_REQUIRE(pfh != nullptr);
|
||||
ATF_REQUIRE(pidfile_fileno(pfh) >= 0);
|
||||
|
||||
struct stat sb;
|
||||
ATF_REQUIRE(fstat(pidfile_fileno(pfh), &sb) == 0);
|
||||
ATF_REQUIRE_EQ(0, sb.st_size);
|
||||
|
||||
freebsd::pidfile pf(pfh);
|
||||
ATF_REQUIRE_EQ(pidfile_fileno(pfh), pf.fileno());
|
||||
|
||||
ATF_REQUIRE(pf.write() == 0);
|
||||
|
||||
ATF_REQUIRE(fstat(pf.fileno(), &sb) == 0);
|
||||
ATF_REQUIRE(sb.st_size > 0);
|
||||
|
||||
ATF_REQUIRE(pf.close() == 0);
|
||||
ATF_REQUIRE(pf.fileno() == -1);
|
||||
ATF_REQUIRE_EQ(EDOOFUS, errno);
|
||||
|
||||
ATF_REQUIRE(unlink("test_pidfile") == 0);
|
||||
}
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, basic);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue