Flow-IPC 1.0.2
Flow-IPC project: Full implementation reference.
util.hpp
Go to the documentation of this file.
1/* Flow-IPC: Core
2 * Copyright 2023 Akamai Technologies, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 * CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License. */
17
18/// @file
19#pragma once
20
21#include "ipc/util/util_fwd.hpp"
24#include <flow/error/error.hpp>
25#include <flow/common.hpp>
26#include <boost/interprocess/exceptions.hpp>
27
28namespace ipc::util
29{
30
31// Template implementations.
32
33template<typename Func>
34void op_with_possible_bipc_exception(flow::log::Logger* logger_ptr, Error_code* err_code,
35 const Error_code& misc_bipc_lib_error,
36 String_view context,
37 const Func& func)
38{
39 using flow::error::Runtime_error;
40 using bipc::interprocess_exception;
41 using boost::system::system_category;
42
43 if (flow::error::exec_void_and_throw_on_error
44 ([&](Error_code* actual_err_code)
45 { op_with_possible_bipc_exception(logger_ptr, actual_err_code, misc_bipc_lib_error, context, func); },
46 err_code, context))
47 {
48 return;
49 }
50 // else
51
52 FLOW_LOG_SET_CONTEXT(logger_ptr, Log_component::S_UTIL);
53
54 try
55 {
56 func();
57 }
58 catch (const interprocess_exception& exc)
59 {
60 /* This code is based off Bipc_mq_handle::op_with_possible_bipc_mq_exception().
61 * It is somewhat simpler, due to lacking the special case to do with MQs.
62 * @todo Unify the 2 somehow, for code reuse.
63 *
64 * Keeping comments light because of that. See that method. */
65
66 const auto native_code_raw = exc.get_native_error();
67 const auto bipc_err_code_enum = exc.get_error_code();
68 FLOW_LOG_WARNING("bipc threw interprocess_exception; will emit some hopefully suitable Flow-IPC Error_code; "
69 "but here are all the details of the original exception: native code int "
70 "[" << native_code_raw << "]; bipc error_code_t enum->int "
71 "[" << int(bipc_err_code_enum) << "]; message = [" << exc.what() << "]; "
72 "context = [" << context << "].");
73 // else
74 if (native_code_raw != 0)
75 {
76 const auto& sys_err_code = *err_code = Error_code(native_code_raw, system_category());
77 FLOW_ERROR_SYS_ERROR_LOG_WARNING();
78 return;
79 }
80 // else
81
82 *err_code = misc_bipc_lib_error; // The earlier WARNING is good enough.
83 return;
84 }
85 // Got here: all good.
86 err_code->clear();
87} // op_with_possible_bipc_exception()
88
89template<typename Handle_name_func>
90void for_each_persistent_impl(const fs::path& persistent_obj_dev_dir_path, const Handle_name_func& handle_name_func)
91{
92 using fs::directory_iterator;
93
94 assert(persistent_obj_dev_dir_path.is_absolute() && "Expecting absolute path like /dev/shm (by contract).");
95
96 /* We could use directory_options::skip_permission_denied => no error if lack permissions for `ls D`; but other
97 * errors are still possible, and we promised to ignore them. So simply do ignore them: eat the Error_code
98 * and let persistent_obj_dev_dir = <the end iterator>. E.g., if there is no error but no contents either,
99 * it'll equal <the end interator> equivalently. */
100 Error_code sink;
101 for (const auto& dir_entry : directory_iterator(persistent_obj_dev_dir_path, sink))
102 {
103 /* In Linux, e.g., /dev/shm/<some pool> is (despite the odd nature of /dev/shm) to be listed as a regular file.
104 * We skip anything else including:
105 * - directories (should not exist but who knows?);
106 * - symlinks (ditto);
107 * - anything else like sockets or other odd things (ditto);
108 * - situation where it could not be determined for some error reason. (Subtlety: directory_entry is, for
109 * optimization, supposed to already store the status before we call is_regular_file(), hence no new
110 * system call occurs therein, but the stored status itself could contain an error. Anyway we simply skip
111 * any non-vanilla situation, so whatever.) (Subtlety 2: std::filesystem::directory_entry specifies
112 * its own .is_regular_file(), but boost.fs lacks this; though the latter is described in terms of
113 * of the free function anyway; so meh.) */
114#ifndef FLOW_OS_LINUX
115 static_assert(false, "We rely on Linux /dev/... (etc.) semantics, where the object-mapped files "
116 "are classified as regular files.");
117#endif
118 Error_code err_code;
119 const auto dir_entry_status = dir_entry.status(err_code);
120 if (err_code || !fs::is_regular_file(dir_entry_status))
121 {
122 continue;
123 }
124 // else
125
126 handle_name_func(Shared_name::ct(dir_entry.path().filename().native()));
127 } // for (dir_entry)
128} // for_each_persistent_impl()
129
130template<typename Handle_name_func>
131void for_each_persistent_shm_pool(const Handle_name_func& handle_name_func)
132{
133#ifndef FLOW_OS_LINUX
134 static_assert(false, "This method relies on/has been tested only with Linux /dev/shm semantics.");
135#endif
136 for_each_persistent_impl("/dev/shm", handle_name_func);
137}
138
139} // namespace ipc::util
static Shared_name ct(const Source &src)
Copy-constructs from a char-sequence container (including string, util::String_view,...
Flow-IPC module containing miscellaneous general-use facilities that ubiquitously used by ~all Flow-I...
void for_each_persistent_impl(const fs::path &persistent_obj_dev_dir_path, const Handle_name_func &handle_name_func)
Implementation of Persistent_object::for_each_persistent(); for example see shm::classic::Pool_arena:...
Definition: util.hpp:90
void for_each_persistent_shm_pool(const Handle_name_func &handle_name_func)
Equivalent to shm::classic::Pool_arena::for_each_persistent().
Definition: util.hpp:131
void op_with_possible_bipc_exception(flow::log::Logger *logger_ptr, Error_code *err_code, const Error_code &misc_bipc_lib_error, String_view context, const Func &func)
Internal (to ipc) utility that invokes the given function that invokes a boost.interprocess operation...
Definition: util.hpp:34
flow::util::String_view String_view
Short-hand for Flow's String_view.
Definition: util_fwd.hpp:115
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Definition: common.hpp:298