From 407b1a3e98f9eb78e72ceab99dbe3389aac19aba Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:25:33 -0400 Subject: [PATCH 01/63] spelling: abstractions Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/g-session_app_org.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/g-session_app_org.dox.txt b/src/doc/manual/g-session_app_org.dox.txt index bcaf70b3a..764423291 100644 --- a/src/doc/manual/g-session_app_org.dox.txt +++ b/src/doc/manual/g-session_app_org.dox.txt @@ -97,7 +97,7 @@ The Manual author(s) must stress that much of the following does not represent h @anchor scope ### Basic concept: data scope ### -The basic problem we are solving here is this: You have your algorithms and data structures, in your meta-application Ap-Bp, and in service of these it is required that you perform IPC. To perform IPC, in the ipc::session paradigm, Flow-IPC *requires* that you use its abtractions, most notably those of `Session_server`, `Server_session` (on open, just `Session`), and `Client_session` (ditto). How to organize your code given your existing algorithms/structures and the aforementioned Flow-IPC abstractions? +The basic problem we are solving here is this: You have your algorithms and data structures, in your meta-application Ap-Bp, and in service of these it is required that you perform IPC. To perform IPC, in the ipc::session paradigm, Flow-IPC *requires* that you use its abstractions, most notably those of `Session_server`, `Server_session` (on open, just `Session`), and `Client_session` (ditto). How to organize your code given your existing algorithms/structures and the aforementioned Flow-IPC abstractions? The key point is that each of your own (IPC-relevant) data structures (and probably related algorithms) should be very cleanly and explicitly classified to have a particular *scope*, a/k/a lifetime. Generally, the scope of each (IPC-relevant) datum is one of the following: - **[Per-]session scope**: The datum begins life no earlier than the creation of the (*opened*!) `Session` (A-B process-to-process conversation) and no later than the (opened) `Session`'s destruction. If the session ends (as earlier noted, when the process exits -- or, far more interestingly, when the *opposing* process exits or dies or gets zombified), then this datum is no longer relevant by definition: The process reponsible for ~half of the algorithm that uses the datum is simply out of commission permanently, at a minimum. From 66df43249693dc3840d0ea5bc23e4c14e1cba7c9 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:09:07 -0400 Subject: [PATCH 02/63] spelling: accessors no Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/f-chan_open.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/f-chan_open.dox.txt b/src/doc/manual/f-chan_open.dox.txt index 79327469a..e4650fece 100644 --- a/src/doc/manual/f-chan_open.dox.txt +++ b/src/doc/manual/f-chan_open.dox.txt @@ -326,7 +326,7 @@ We've covered pretty much every approach for opening channels via ipc::session. }); ~~~ -On the active-open side it is accomplished as follows: a different overload of `open_channel()` also takes a metadata structure, a blank one first being obtained via `Session::mdt_builder()` and then typically modified with some capnp-generated accessorsno differently fromn the pre-session-open metadata example @ref chan_open_mdt_ex "here." +On the active-open side it is accomplished as follows: a different overload of `open_channel()` also takes a metadata structure, a blank one first being obtained via `Session::mdt_builder()` and then typically modified with some capnp-generated accessors no differently fromn the pre-session-open metadata example @ref chan_open_mdt_ex "here." ~~~ Channel new_channel; From ab0ee3e5236ae5a323b97dc32a3669f312eeba39 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:05:39 -0400 Subject: [PATCH 03/63] spelling: accessors Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/l-transport_shm.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/l-transport_shm.dox.txt b/src/doc/manual/l-transport_shm.dox.txt index 35e9307d8..101d3611d 100644 --- a/src/doc/manual/l-transport_shm.dox.txt +++ b/src/doc/manual/l-transport_shm.dox.txt @@ -118,7 +118,7 @@ SHM-backed capabilities become available, like everything else in the ipc::sessi - An **app-scope arena** (a/k/a `.app_shm()`), for that specific distinct `Client_app`, is created. This arena's **lifetime** is *until the `Session_server` is destroyed*. That is: its lifetime spans all future sessions, not just the one that triggered its creation (in on-demand fashion). - If the app-scope arena has already been created, it is not re-created; but it is made equally accessible via `.app_shm()` accessors. -@note With SHM-jemalloc the app-scope arena is accessible (can be allocated in) only on the session-server end. The `.app_shm()` accesors do not exist on the session-client end. +@note With SHM-jemalloc the app-scope arena is accessible (can be allocated in) only on the session-server end. The `.app_shm()` accessors do not exist on the session-client end. --- From aa698bb57769a5eac703e296b9d478fff074fd50 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:06:13 -0400 Subject: [PATCH 04/63] spelling: arbitrary Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/b-api_overview.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/b-api_overview.dox.txt b/src/doc/manual/b-api_overview.dox.txt index d3c9e5502..4704ce956 100644 --- a/src/doc/manual/b-api_overview.dox.txt +++ b/src/doc/manual/b-api_overview.dox.txt @@ -103,7 +103,7 @@ Having obtained a `Session`, the application can open transport channels (and, i > > // NOTE: Upon opening session, capabilities of `session` on either side are **exactly the same**. > // Client/server status matters only when establishing the IPC conversation; -> // the conversation itself once established is arbitrariy and up to you fully. +> // the conversation itself once established is arbitrary and up to you fully. > ~~~ > > Open channel(s) in a session: From 2f7eb00b9214959d416fb246af5d136184aeaec7 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:02:35 -0400 Subject: [PATCH 05/63] spelling: are Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/e-session_setup.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/e-session_setup.dox.txt b/src/doc/manual/e-session_setup.dox.txt index ce4990563..e793145bf 100644 --- a/src/doc/manual/e-session_setup.dox.txt +++ b/src/doc/manual/e-session_setup.dox.txt @@ -50,7 +50,7 @@ For our purposes let's assume we've chosen application Ap (server) and Bp (clien @anchor universe_desc Specifying IPC universe description: ipc::session::App ------------------------------------------------------ -Conceptually, Ap and Bp are both **applications**, so each has certain basic properties (such as executable name). In addition, Ap takes the role of a server in our split, while Bp takes the role of a client; and in that role Ap has certain additional server-only properties (such as a list of client applications that may establish sessions with it -- in our case just Bp). In order for ipc::session::Session hierarchy to work properly when establishing a session, you must provide all of that information to it. This is done very straightforwardly by filling out simple `struct`s of types ipc::session::App, @link ipc::session::Client_app Client_app@endlink, and @link ipc::session::Server_app Server_app@endlink. Together these are are the **IPC universe description**. +Conceptually, Ap and Bp are both **applications**, so each has certain basic properties (such as executable name). In addition, Ap takes the role of a server in our split, while Bp takes the role of a client; and in that role Ap has certain additional server-only properties (such as a list of client applications that may establish sessions with it -- in our case just Bp). In order for ipc::session::Session hierarchy to work properly when establishing a session, you must provide all of that information to it. This is done very straightforwardly by filling out simple `struct`s of types ipc::session::App, @link ipc::session::Client_app Client_app@endlink, and @link ipc::session::Server_app Server_app@endlink. Together these are the **IPC universe description**. To avoid confusion and errors down the line it is important to keep to a simple rule (which is nevertheless tempting to break): The IPC universe description (the `App`s/`Client_app`s/`Server_app`s combined) may be a simple and small thing, but there is conceptually *only one* of it. So when various little parts of that universe are passed-in to (most notably) `Session_server` and `Client_session` constructors, their values must never conflict; they must be equal on each side. So if application Ap lives at "/bin/a.exec" and has UID 322, then both application Ap and application Bp must know those property values for application Ap -- as must application Cp, if it's also a part of the universe. We'll show this more practically below, but just remember this rule. From 726f2ef4d83b00863d27cf10b67c7eaff5d3c740 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:06:20 -0400 Subject: [PATCH 06/63] spelling: artifact Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d9a44386e..4bdc3a41b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -52,7 +52,7 @@ name: Flow-IPC pipeline # *testing the ability to generate it*. It's a subtle difference, but it's important to note it, because # if we wanted to test the ins and outs of doc generation in various environments then we could have a much more # complex and longer pipeline -- and perhaps we should... but that's not the goal *here*. -# - Output: Make it available as workflow artfiact for download via GitHub Actions UI. +# - Output: Make it available as workflow artifact for download via GitHub Actions UI. # Hence human can simply download it, whether it's for the `main` tip or a specific release version. # - Side effect: (On pushes/merges to `main` branch *only*) Check-in the *generated docs* back into `main` # itself, so that (1) they're available for local perusal by any person cloning/pulling `main` and (2) ditto From b58ea4494218df70c22bd80a1e9dfcbd45306446 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:06:39 -0400 Subject: [PATCH 07/63] spelling: available Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index d31f1a5f6..9b99dc07a 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -99,7 +99,7 @@ To build Flow-IPC (including Flow): but the basics are as follows. CMake is very flexible and powerful; we've tried not to mess with that principle in our build script(s). 1. Choose a tool. `ccmake` will allow you to interactively configure aspects of the build system, including - showing docs for various knobs our CMakeLists.txt (and friends) have made availale. `cmake` will do so without + showing docs for various knobs our CMakeLists.txt (and friends) have made available. `cmake` will do so without asking questions; you'll need to provide all required inputs on the command line. Let's assume `cmake` below, but you can use whichever makes sense for you. 2. Choose a working *build directory*, somewhere outside the present `ipc` distribution. Let's call this From acb91eb8f7d831cfc7ffc5ff62a414bea502eaa4 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:02:43 -0400 Subject: [PATCH 08/63] spelling: become Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/g-session_app_org.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/g-session_app_org.dox.txt b/src/doc/manual/g-session_app_org.dox.txt index 764423291..78c29aa94 100644 --- a/src/doc/manual/g-session_app_org.dox.txt +++ b/src/doc/manual/g-session_app_org.dox.txt @@ -78,7 +78,7 @@ In case of ungraceful shutdown, usually via `abort()`: The RAM may leak temporar --- -Okay, but -- in the case of partner-triggered session closure -- how do we detect that the partner has indeed closed it, either gracefully or ungracefully, or has become become unhealthy/zombified? This is more complex than destroying the `Session` (plus possibly other `Session`(s) and/or `Session_server`) that follows it, but it's also done via a well-defined API. To wit: this is the error handler which we've omitted in (@ref session_setup) examples so far. As shown in that Manual page, the error handler is supplied to @link ipc::session::Client_session::Client_session() `Client_session` constructor@endlink or @link ipc::session::Server_session::init_handlers() Server_session::init_handlers()@endlink. Recall these both must be called strictly before the session is officially considered opened. +Okay, but -- in the case of partner-triggered session closure -- how do we detect that the partner has indeed closed it, either gracefully or ungracefully, or has become unhealthy/zombified? This is more complex than destroying the `Session` (plus possibly other `Session`(s) and/or `Session_server`) that follows it, but it's also done via a well-defined API. To wit: this is the error handler which we've omitted in (@ref session_setup) examples so far. As shown in that Manual page, the error handler is supplied to @link ipc::session::Client_session::Client_session() `Client_session` constructor@endlink or @link ipc::session::Server_session::init_handlers() Server_session::init_handlers()@endlink. Recall these both must be called strictly before the session is officially considered opened. `Session` keeps track of partner-triggered session closure, which we term the **session becoming hosed** (a/k/a **session-hosing conditions**). Yes, really. Once detected, it *immediately* triggers the error handler you supplied. Since it is potentially important for your peace of mind, at least the following (internal) conditions will lead to session-hosing: - An internally maintained (for various needs but most importantly channel-opening negotiations) *session master channel* uses a local (Unix-domain) stream socket connection; and that socket connection has become gracefully, or ungracefully, closed by the opposing side. A graceful closure would (internally) involve a TCP-FIN-like end-of-"file" condition being received from the opposing side; usually indicating a clean `exit()`. An ungraceful closure would (internally) involve a TCP-RST-like error condition (ECONNRESET, EPIPE) being received from the opposing side; usually indicating an `abort()` or similar. From 69aa25caf56e28b7ce5bd10e0ec13483df95fe71 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:06:49 -0400 Subject: [PATCH 09/63] spelling: becomes Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/script_interpreter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/transport_test/script_interpreter.cpp b/test/suite/transport_test/script_interpreter.cpp index c2752e047..2e07f41a0 100644 --- a/test/suite/transport_test/script_interpreter.cpp +++ b/test/suite/transport_test/script_interpreter.cpp @@ -1667,7 +1667,7 @@ void Script_interpreter::cmd_chan_bundle_create() /* Got here: mq_out, mq_in are ready. We have sock_stm also. We can now bundle them all into * Mqs_socket_stream_channel. - * As advertised, as we do so, the sock_stm in the slot gets "eaten" (becames a NULL-state Native_socket_stream). + * As advertised, as we do so, the sock_stm in the slot gets "eaten" (becomes a NULL-state Native_socket_stream). * This happens via move-semantics. So the sock_stm in the slot becomes unusable by itself. */ FLOW_LOG_INFO("Wrapping all 3 peers [" << *mq_in << "] [" << *mq_out << "] [" << *sock_stm << "] in a new " From 1939d2528c9360374ed10757e102fb9bb2b6dcc2 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:07:14 -0400 Subject: [PATCH 10/63] spelling: certainly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/j-chan_struct.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/j-chan_struct.dox.txt b/src/doc/manual/j-chan_struct.dox.txt index a40b4c997..4ddd79d01 100644 --- a/src/doc/manual/j-chan_struct.dox.txt +++ b/src/doc/manual/j-chan_struct.dox.txt @@ -693,7 +693,7 @@ The channel might get hosed *at any time*. Consider this code: Chronologically: -# Point X: We've called `.expect_msg()`. Say it returned `true` which means the channel is *not* hosed at that exact point in time. It, itself, lacks an `err_code` arg in its signature, so it cannot itself emit a new error. - -# Point A: Apparently a message has arrived. So at that exact point the channel is *not* hosed either. Even if it is, `.create_msg()` has nothing to do with transmitting anything, and certainyl all the message-reading and -filling logic is orthogonal to the channel itself. No problem. + -# Point A: Apparently a message has arrived. So at that exact point the channel is *not* hosed either. Even if it is, `.create_msg()` has nothing to do with transmitting anything, and certainly all the message-reading and -filling logic is orthogonal to the channel itself. No problem. -# Point B: Here we `.send()`. That's a transmission-related API, and moreover it can itself emit a (new) error. Anyway, we don't know if the channel is hosed or not per se, and there's only one way to find out: call it. -# Point C: Now there are 2 error-related outputs: `ok` (return value) and `err_code` (out-arg). (We could have passed-in null or omitted arg -- same thing -- in which case we'd need to be ready to catch resulting exception.) - Suppose `ok == true`, but `err_code` is truthy. That would indicate *new channel-hosing error* being emitted. Hence we call `teardown()` which will stop work on this channel -- deinitialize whatever, etc. From e7456487eb96c3397b7ee50848d2751082092626 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:07:31 -0400 Subject: [PATCH 11/63] spelling: commercial Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/h-safety_perms.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/h-safety_perms.dox.txt b/src/doc/manual/h-safety_perms.dox.txt index c2e8f93bc..9623ca010 100644 --- a/src/doc/manual/h-safety_perms.dox.txt +++ b/src/doc/manual/h-safety_perms.dox.txt @@ -80,7 +80,7 @@ Lastly, SHM-jemalloc (as of this writing, though this could be optionally change @anchor shm_safety_other_considerations @par Other aspects of SHM-classic versus SHM-jemalloc choice -Safety is a major factor w/r/t which to choose, but it is not the *only* factor. This is outside our scope here, but for convenience we restate: Spoiler alert: SHM-classic is fast/low-risk to set up and tear down (meaning, the logic executed during session/server opening and closing), lightning-fast in lend/borrow operations, easy to debug and understand, allows full symmetric read/write, and provides app-scope arena allocation on both sides (as opposed to only the session-server side). SHM-jemalloc, in contrast, lacks those benefits but packs a *huge* benefit that arguably more than makes up for them: the use of commercial-grade *jemalloc `malloc()` memory manager* for heap management, at allocation (`Arena::construct(...)`) and deallocation time. (SHM-classic uses a [built-in algorithm](https://www.boost.org/doc/libs/1_82_0/doc/html/interprocess/memory_algorithms.html) by the Boost guys, or whatever replacement one can cook up to replace it. Out of the box this lacks jemalloc perf-boosting goodies like mature fragmentation avoidance algorithms and thread caching: things we take for granted in conventional stack-and-heap-based memory use. It may be absolutely fine for many applications, but it is no commerical-grade `malloc()`er.) +Safety is a major factor w/r/t which to choose, but it is not the *only* factor. This is outside our scope here, but for convenience we restate: Spoiler alert: SHM-classic is fast/low-risk to set up and tear down (meaning, the logic executed during session/server opening and closing), lightning-fast in lend/borrow operations, easy to debug and understand, allows full symmetric read/write, and provides app-scope arena allocation on both sides (as opposed to only the session-server side). SHM-jemalloc, in contrast, lacks those benefits but packs a *huge* benefit that arguably more than makes up for them: the use of commercial-grade *jemalloc `malloc()` memory manager* for heap management, at allocation (`Arena::construct(...)`) and deallocation time. (SHM-classic uses a [built-in algorithm](https://www.boost.org/doc/libs/1_82_0/doc/html/interprocess/memory_algorithms.html) by the Boost guys, or whatever replacement one can cook up to replace it. Out of the box this lacks jemalloc perf-boosting goodies like mature fragmentation avoidance algorithms and thread caching: things we take for granted in conventional stack-and-heap-based memory use. It may be absolutely fine for many applications, but it is no commercial-grade `malloc()`er.) --- From b60b3b9b13e84ccf39cf3ae5f36e80223fa1a400 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:07:40 -0400 Subject: [PATCH 12/63] spelling: conveniently Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index 9b99dc07a..d5153e61b 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -160,7 +160,7 @@ The documentation consists of: - (minor) comments, about the build, in `CMakeLists.txt`, `*.cmake`, `conanfile.py` (in various directories including this one where the top-level `CMakeLists.txt` lives); - (major/main) documentation directly in the comments throughout the source code; these have been, - and can be again, conviently generated using certain tools (namely Doxygen and friends), via the + and can be again, conveniently generated using certain tools (namely Doxygen and friends), via the above-shown `make ipc_doc_public ipc_doc_full flow_doc_public flow_doc_full` command. - The generated documentation consists of: - (Flow-IPC proper) a clickable guided Manual + Reference. From 205a9a0e27ab53a8067e2a937f8438e4a8c50279 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:43:36 -0400 Subject: [PATCH 13/63] spelling: ctrl Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/transport_test/README.txt b/test/suite/transport_test/README.txt index ac52320b4..7d8e39bfa 100644 --- a/test/suite/transport_test/README.txt +++ b/test/suite/transport_test/README.txt @@ -27,7 +27,7 @@ The tool: - writes Flow-IPC logs to file log (2nd arg) with sev (4th arg); [data] and [trace] are useful; [info] is good as a way to check realistically the verbosity level of the library APIs (do note sometimes timeouts in in-script are so tight that using [data] or [trace] may lead to a test failure due to timeout); - - reads/parses the entire script for STDIN, then executes it in order (so either type all lines, Ctlr-D; or redirect + - reads/parses the entire script for STDIN, then executes it in order (so either type all lines, Ctrl-D; or redirect from a file); - acts synchronously: each command completes before the next starts (and if it fails, the program exits). From 9cb767b2df373aab3b69f3d2760b36a59c64739d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:08:17 -0400 Subject: [PATCH 14/63] spelling: destructor Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/g-session_app_org.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/g-session_app_org.dox.txt b/src/doc/manual/g-session_app_org.dox.txt index 78c29aa94..12c42305d 100644 --- a/src/doc/manual/g-session_app_org.dox.txt +++ b/src/doc/manual/g-session_app_org.dox.txt @@ -53,7 +53,7 @@ So let's get into the relatively easy topic: the API for closing an open session If the closing trigger is *local*, then one simply destroys the `Session` object (its destructor getting called), or in the case of the server side potentially 1+ `Session` object(s). That's it. Then it can exit the process. -@note When locally-triggered (process is exiting gracefully), a session-server should, also, destroy the `Session_server` object (its destrctuctor getting called). The order does not matter; for example `Session_server` can be destroyed first. +@note When locally-triggered (process is exiting gracefully), a session-server should, also, destroy the `Session_server` object (its destructor getting called). The order does not matter; for example `Session_server` can be destroyed first. If the closing trigger is the peer *partner*, then one... also simply destroys the one, relevant `Session` object. Then one either attempts to start another session (if a session-client, or server acting equally to a client), or does nothing (if acting as a server that can accept arbitrary number of concurrent sessions anyway). From 21f7c8522e647e0dd00392a3fef8234e149fe893 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:09:21 -0400 Subject: [PATCH 15/63] spelling: duplex Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/script_interpreter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/transport_test/script_interpreter.cpp b/test/suite/transport_test/script_interpreter.cpp index 2e07f41a0..43f269a6c 100644 --- a/test/suite/transport_test/script_interpreter.cpp +++ b/test/suite/transport_test/script_interpreter.cpp @@ -190,7 +190,7 @@ const util::String_view S_KEYWD_CHAN_BUNDLE_BIPC_RECV_BLOB = "CHAN_BUNDLE_BIPC_R /* Test {Posix_mqs_socket_stream_channel|Bipc_mqs_socket_stream_channel}::ctor (creation). Really this operation * composes a number of things which are more carefully tested by other commands above. So mostly this is a setup * command, so that we can then test send/receive transmission over the Channel which bundles 2 unidirectional - * MQ pipes and a full-fuplex Native_socket_stream pipe. In particular it expects to always succeed: failure + * MQ pipes and a full-duplex Native_socket_stream pipe. In particular it expects to always succeed: failure * of ctor call shall always fail the test. As such, to successfully use this, the other side (in this or other * invocation of Script_interpreter) shall invoke a similar command: * - Its must be the same. From a7745dd6dc29089fe96becc5dca6eb4c532a7e05 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:03:32 -0400 Subject: [PATCH 16/63] spelling: during Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4bdc3a41b..e1f579cd4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -689,7 +689,7 @@ jobs: # As it stands, whatever matrix compiler/build-type is chosen applies not just to our code (correct) # and 3rd party libraries we link like lib{boost_*|capnp|kj|jemalloc} (semi-optional but good) but also # unfortunately any items built from source during "Install Flow-IPC dependencies" step that we then - # use during during the build step for our own code subsequently. At a minimum this will slow down + # use during the build step for our own code subsequently. At a minimum this will slow down # such programs. (For the time being we accept this as not-so-bad; to target this config at some things # but not others is hard/a ticket.) In particular, though, the capnp compiler binary is built this way; # and our "Build targets" step uses it to build key things (namely convert .capnp schemas into .c++ From f99b278c611e8f6d7a1c275307af78b2a1932cf9 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:08:31 -0400 Subject: [PATCH 17/63] spelling: establishing Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e1f579cd4..b77c54456 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1087,7 +1087,7 @@ jobs: # The following [Exercise mode] tests follow the instructions in bin/transport_test/README.txt. # Note that the creation of ~/bin/ex_..._run and placement of executables there, plus # /tmp/var/run for run-time files (PID files and similar), is a necessary consequence of - # the ipc::session safety model for estabshing IPC conversations (sessions). + # the ipc::session safety model for establishing IPC conversations (sessions). - name: Prepare IPC-session safety-friendly run-time environment for [transport_test - Exercise mode] if: | From 2db408e962cbc5c9dd95949bc8fdfac6062b8b47 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:09:11 -0400 Subject: [PATCH 18/63] spelling: from Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/f-chan_open.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/f-chan_open.dox.txt b/src/doc/manual/f-chan_open.dox.txt index e4650fece..f0c3ce3dd 100644 --- a/src/doc/manual/f-chan_open.dox.txt +++ b/src/doc/manual/f-chan_open.dox.txt @@ -326,7 +326,7 @@ We've covered pretty much every approach for opening channels via ipc::session. }); ~~~ -On the active-open side it is accomplished as follows: a different overload of `open_channel()` also takes a metadata structure, a blank one first being obtained via `Session::mdt_builder()` and then typically modified with some capnp-generated accessors no differently fromn the pre-session-open metadata example @ref chan_open_mdt_ex "here." +On the active-open side it is accomplished as follows: a different overload of `open_channel()` also takes a metadata structure, a blank one first being obtained via `Session::mdt_builder()` and then typically modified with some capnp-generated accessors no differently from the pre-session-open metadata example @ref chan_open_mdt_ex "here." ~~~ Channel new_channel; From 778c13b71167e9c0cf7d4eda5c623e35b8eba2bf Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:09:28 -0400 Subject: [PATCH 19/63] spelling: further Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/f-chan_open.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/f-chan_open.dox.txt b/src/doc/manual/f-chan_open.dox.txt index f0c3ce3dd..7c8816c3f 100644 --- a/src/doc/manual/f-chan_open.dox.txt +++ b/src/doc/manual/f-chan_open.dox.txt @@ -352,7 +352,7 @@ In the somewhat advanced situation where one wants to use both methods of channe struct InitChannelCfg { numStructuredChannels @0 :Size; - # Futher stuff... needn't just be scalars either. + # Further stuff... needn't just be scalars either. } struct OnDemandChannelCfg { From ecc8ba0d551159470c77a0821e501d341c819a35 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:09:40 -0400 Subject: [PATCH 20/63] spelling: google Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/unit_test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/unit_test/CMakeLists.txt b/test/suite/unit_test/CMakeLists.txt index b5f8b14c2..80ad112b6 100644 --- a/test/suite/unit_test/CMakeLists.txt +++ b/test/suite/unit_test/CMakeLists.txt @@ -76,7 +76,7 @@ find_package(CapnProto CONFIG REQUIRED) # The relevant translation units (.cpp, .capnp -> .c++) shall be listed directly below, in normal CMake fashion, # under the relevant unit-test executables. We do not make an intermediate libtest* or anything like that; # the relevant object files are compiled directly from their relevant source files. (This is pretty common -# when using the GOogle unit-test framework.) Do note, again, that those relevant source files are directly +# when using the Google unit-test framework.) Do note, again, that those relevant source files are directly # under the sub-projects' source trees: ipc_*/src/.../test/.... # # This executable, libipc_unit_test, is the compendium of unit tests to execute. From bc9f0f60bdef4063f2f09b94730150c864eccf31 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:10:15 -0400 Subject: [PATCH 21/63] spelling: ignore Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b77c54456..fc89e8f39 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -720,7 +720,7 @@ jobs: # sanitizers' suppressions. (Note, though, that MSAN does not have a run-time suppression # system; only these ignore-lists. The others do also have ignore-lists though. # The format is totally different between the 2 types of suppression.) - # Our MSAN support is budding compared to UBSAN/ASAN/TSAN; so just specify the one ingore-list file + # Our MSAN support is budding compared to UBSAN/ASAN/TSAN; so just specify the one ignore-list file # we have now. TODO: If/when MSAN support gets filled out like the others', then use a context system # a-la env.setup-tests-env. cat ${{ github.workspace }}/flow/src/sanitize/msan/ignore_list_${{ matrix.compiler.name }}.cfg \ From 867157a161c19b95d81f11cab27bb24557931f32 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:10:08 -0400 Subject: [PATCH 22/63] spelling: individual Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/g-session_app_org.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/g-session_app_org.dox.txt b/src/doc/manual/g-session_app_org.dox.txt index 12c42305d..549281ea2 100644 --- a/src/doc/manual/g-session_app_org.dox.txt +++ b/src/doc/manual/g-session_app_org.dox.txt @@ -129,7 +129,7 @@ Let's have a (singleton, really) `class Process {}` just to bracket things nicel - Session-server `Process`: - The local `Server_app` is needed when constructing the `Session_server`. This is normally done only once, and it is reasonable to do so in `Process` constructor; but if that action is delayed beyond that point, then you'll need the `Server_app` available and may wish to keep it as a data member in `Process`. - Same for the master `Client_app` list, which we in the past called `MASTER_APPS_AS_CLI`. - - Lastly, each individial `Client_app` that is listed in ipc::session::Server_app::m_allowed_client_apps -- as individual data members (like `Client_app m_cli_app_b` and `Client_app m_cli_app_c`), may be helpful for multi-client-application setups (i.e., if we are Ap, and Bp and Cp may establish sessions we us). For example, when deciding which part of your session-server application shall deal with a newly-opened `Session`, `Session::client_app()` is the actual `Client_app connecting_cli` as a handler argument. So then you could do, like, `if (session.client_app()->m_name == m_cli_app_b.m_name) { ...start the app Bp session... } else ...etc...`. + - Lastly, each individual `Client_app` that is listed in ipc::session::Server_app::m_allowed_client_apps -- as individual data members (like `Client_app m_cli_app_b` and `Client_app m_cli_app_c`), may be helpful for multi-client-application setups (i.e., if we are Ap, and Bp and Cp may establish sessions we us). For example, when deciding which part of your session-server application shall deal with a newly-opened `Session`, `Session::client_app()` is the actual `Client_app connecting_cli` as a handler argument. So then you could do, like, `if (session.client_app()->m_name == m_cli_app_b.m_name) { ...start the app Bp session... } else ...etc...`. Whatever you do store should be listed in `Process { private: }` section first, as subsequent data items will need them. From 8d07506c6096abc2dfc892b9aab313df3e17e05f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:15:39 -0400 Subject: [PATCH 23/63] spelling: maintainability Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fc89e8f39..87dd91ed5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -635,7 +635,7 @@ jobs: # hidden configure-script-generated binary abort => capnp binary build fails. # - capnp binary fails MSAN at startup; hence capnp-compilation of our .capnp schemas fails. # We have worked around all these, so the thing altogether works. It's just somewhat odd and entropy-ridden; - # and might cause maintanability problems over time, as it has already in the past. + # and might cause maintainability problems over time, as it has already in the past. # The TODO is to be more judicious about it # and only apply these things to the libs/executables we want it applied. It is probably not so simple; # but worst-case it should be possible to use something like build-type-cflags-override to target our code; @@ -804,7 +804,7 @@ jobs: # Here, as in all other tests below, we assemble a suppressions file in case this is a sanitized # run; and we follow the procedure explained near setup-tests-env definition. To reiterate: to avoid - # tedium, but at the cost of mantainability of this file (meaning if a suppressions context is added then + # tedium, but at the cost of maintainability of this file (meaning if a suppressions context is added then # a few lines would need to be added here), we only list those contexts where *any* sanitizer has # *any* suppression; otherwise we skip it for brevity. `find . -name 'suppressions*.cfg` is pretty useful # to determine their presence in addition to whether the test itself has its specific suppressions of any kind. From 1cc2d10464aa7f92c711d4dfae47dfc554390693 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:17:09 -0400 Subject: [PATCH 24/63] spelling: meanwhile Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/k-chan_struct_advanced.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/k-chan_struct_advanced.dox.txt b/src/doc/manual/k-chan_struct_advanced.dox.txt index 3a61e3228..b2b77b5de 100644 --- a/src/doc/manual/k-chan_struct_advanced.dox.txt +++ b/src/doc/manual/k-chan_struct_advanced.dox.txt @@ -108,7 +108,7 @@ For SHM-backed messages it is more fun, as the message and subsequent message in Thus, conceptually, there is a ref-count: 1 for the `Msg_out`; 1 for each `Msg_in`. Once it reaches zero, the lifetime of the data ends, and the RAM resources are returned for use by other items. (This is all thread-safe in cross-process fashion. It's fine if destructors run concurrently to each other, with a new related `Msg_in` being created in another process, etc.) -@note `Msg_in`s are exclusively trafficked via `Msg_in_ptr`s which are mere `shared_ptr`s; hence once a particular `shared_ptr` group reaches ref-count-zero, the destructor is invoked, and voilĂ  for that particular *one* message instance. This applies regardless of SHM-backed versus heap-backed messages. Meanwile `Msg_out` can live wherever you want (you can wrap it in a `shared_ptr` if you want); but don't confuse where these *objects* live as opposed to where the *data structure* lives (similarly to a regular `std::vector` potentially living on the stack but allocating its buffer elsewhere, typically heap but depending on the `Allocator` used elsewhere). +@note `Msg_in`s are exclusively trafficked via `Msg_in_ptr`s which are mere `shared_ptr`s; hence once a particular `shared_ptr` group reaches ref-count-zero, the destructor is invoked, and voilĂ  for that particular *one* message instance. This applies regardless of SHM-backed versus heap-backed messages. Meanwhile `Msg_out` can live wherever you want (you can wrap it in a `shared_ptr` if you want); but don't confuse where these *objects* live as opposed to where the *data structure* lives (similarly to a regular `std::vector` potentially living on the stack but allocating its buffer elsewhere, typically heap but depending on the `Allocator` used elsewhere). @anchor msg_ct ### Constructing messages; reusing messages among different `struc::Channel`s ### From cf34308721f1d2453763e6bcd5d5377b08c1bbb9 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:20:30 -0400 Subject: [PATCH 25/63] spelling: naturally Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/j-chan_struct.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/j-chan_struct.dox.txt b/src/doc/manual/j-chan_struct.dox.txt index 4ddd79d01..d3516f6e4 100644 --- a/src/doc/manual/j-chan_struct.dox.txt +++ b/src/doc/manual/j-chan_struct.dox.txt @@ -577,7 +577,7 @@ Now then: That's about unsolicited messages. *Responses* are different. Receiv That feature -- the local and "remote" unexpected-reponse notification -- may be useful. Informally, though, we would suggest designing a protocol in robust enough fashion to where these guys firing would be impossible. It should really, usually, be possible to lock down your protocol to avoid races or corner cases of that nature. Though, who knows? It's conceivable that it's not always so easy. Just saying: try to keep it simple. @par sync_io-pattern and expect-message(s) -The doc header for ipc::transport::struc::sync_io::Channel::expect_msg() and @link ipc::transport::struc::sync_io::Channel::expect_msgs() .expect_msgs()@endlink explains the deal. For your convenience here, though, spoiler alert: As noted above, async-I/O `.expect_msg*()` may trigger a "burst" of cached in-message(s) being emitted via the very handler that was just given to that method; but with `sync_io` pattern this situation creates a dichotomy: An in-message being available immediately is not quite the same as one being available asynchronously later. Therefore the `sync_io`-pattern `.expect_msg*()` API features an extra out-argument. If message(s) is/are available synchronously, it/they is/are synchronously output right into that argument. (`.expect_msg()`, natually, emits up to 1 in-message, and if 1 was indeed emitted does not register an expectation for more -- and forgets the handler, never invoking it. `.expect_msgs()` can emit multiple in-messages synchronously into a user-supplied sequence container, and even if it does so, it remembers the handler in case more arrive later.) +The doc header for ipc::transport::struc::sync_io::Channel::expect_msg() and @link ipc::transport::struc::sync_io::Channel::expect_msgs() .expect_msgs()@endlink explains the deal. For your convenience here, though, spoiler alert: As noted above, async-I/O `.expect_msg*()` may trigger a "burst" of cached in-message(s) being emitted via the very handler that was just given to that method; but with `sync_io` pattern this situation creates a dichotomy: An in-message being available immediately is not quite the same as one being available asynchronously later. Therefore the `sync_io`-pattern `.expect_msg*()` API features an extra out-argument. If message(s) is/are available synchronously, it/they is/are synchronously output right into that argument. (`.expect_msg()`, naturally, emits up to 1 in-message, and if 1 was indeed emitted does not register an expectation for more -- and forgets the handler, never invoking it. `.expect_msgs()` can emit multiple in-messages synchronously into a user-supplied sequence container, and even if it does so, it remembers the handler in case more arrive later.) --- From a51a437b549fe5191037d80491e126bcef81fc1f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:21:08 -0400 Subject: [PATCH 26/63] spelling: objects Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/h-safety_perms.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/h-safety_perms.dox.txt b/src/doc/manual/h-safety_perms.dox.txt index 9623ca010..35cd4c584 100644 --- a/src/doc/manual/h-safety_perms.dox.txt +++ b/src/doc/manual/h-safety_perms.dox.txt @@ -68,7 +68,7 @@ Consider a simple-enough scenario in which applications Ap and Bp have an A-B se With SHM-classic: `session->session_shm()`, on either side, are both really referring to the *same* SHM arena (in fact, same pool as of this writing). Process B never writes (in our stipulation above) to objects/messages received from A, but process B does its own allocations which *do* write to the same SHM-pool as one where A-written/allocated data do reside. In fact (as we stipulated) the buffer-overflow bug wrote where it wasn't supposed to within `session->session_shm()` pool (from B's perspective)... but that's the same pool as A. And when they allocate "their" respective objects, they're allocating from the same memory area, using a shared set of memory-manager control data (allocation state). So, the bottom line is, A -- having detected B's ill health/death -- cannot safely continue operating on *its* data structures it has allocated or wants to allocate (or deallocate) subsequently. B died, but A-"owned" data are no longer safe. -The same is true of `session->app_shm()` ([app-scope](./session_app_org.html#scope) data). If B ever allocates messages and/or obejcts in its `session->app_shm()` and then goes down ungracefully, A -- to remain safe-ish -- must drop *all* app-scope data thus affecting potentially all other sessions A has ongoing. In fact, SHM-classic's operation involves B writing to the shared SHM-pool even if it, itself, *never* allocates out-messages or structures (i.e., is logically entirely read-only). (Internally, when one `lend_object()`s an object from A to `borrow_object()`ing B, SHM-classic atomically-increments a hidden ref-count near the object. ipc::transport::struc::Channel::send() and `*sync_request()` internally invoke these lend-borrow operations as well.) So, even if B is logically read-only, an ungraceful death of B still involves *some* safety risk to A-owned data in SHM. +The same is true of `session->app_shm()` ([app-scope](./session_app_org.html#scope) data). If B ever allocates messages and/or objects in its `session->app_shm()` and then goes down ungracefully, A -- to remain safe-ish -- must drop *all* app-scope data thus affecting potentially all other sessions A has ongoing. In fact, SHM-classic's operation involves B writing to the shared SHM-pool even if it, itself, *never* allocates out-messages or structures (i.e., is logically entirely read-only). (Internally, when one `lend_object()`s an object from A to `borrow_object()`ing B, SHM-classic atomically-increments a hidden ref-count near the object. ipc::transport::struc::Channel::send() and `*sync_request()` internally invoke these lend-borrow operations as well.) So, even if B is logically read-only, an ungraceful death of B still involves *some* safety risk to A-owned data in SHM. Now consider SHM-jemalloc. A's `session->session_shm()` is a SHM-arena maintained (internally) by A; B's `session->session_shm()` is a completely separate arena maintained by B. B went down? Though the user code that uses SHM-jemalloc can remain (almost) completely identical to SHM-classic alternative, once B is down: Data allocated and written by A, in its `session->session_shm()`, remain safe to use. From 36be929dd55fe1251f2259bebc87810ab029fa64 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:21:31 -0400 Subject: [PATCH 27/63] spelling: parameter Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/l-transport_shm.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/l-transport_shm.dox.txt b/src/doc/manual/l-transport_shm.dox.txt index 101d3611d..2fee14bf8 100644 --- a/src/doc/manual/l-transport_shm.dox.txt +++ b/src/doc/manual/l-transport_shm.dox.txt @@ -198,7 +198,7 @@ So that would definitely be taxing to code. And indeed, particularly with legac @warning As a rule `std::` containers are not SHM-friendly, at least in gcc as of gcc-9; they assume raw-pointer-using allocators. By contrast `boost::container::*` corrected those issues. `std::vector` happens to be okay in gcc-8 at least, but it's safer to just go with `boost::container`. E.g., its `std::list` bro is broken in this regard. -Once you've chosen your STL-compliant SHM-friendly container type -- or developed your own! -- you must take care to, also, specify (as the `Allocator` template paramater to the container type) the **SHM-allocating allocator** we've provided. (boost.interprocess provides an allocator template for similar use; but it is stateful, which is a huge pain in the butt -- plus it uses additional RAM to store the allocator pointer.) Use this allocator: +Once you've chosen your STL-compliant SHM-friendly container type -- or developed your own! -- you must take care to, also, specify (as the `Allocator` template parameter to the container type) the **SHM-allocating allocator** we've provided. (boost.interprocess provides an allocator template for similar use; but it is stateful, which is a huge pain in the butt -- plus it uses additional RAM to store the allocator pointer.) Use this allocator: ~~~ template From 0a06bd0566a705904dc4ee7dab4afe9a3adca3ad Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:22:46 -0400 Subject: [PATCH 28/63] spelling: parameters Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/k-chan_struct_advanced.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/k-chan_struct_advanced.dox.txt b/src/doc/manual/k-chan_struct_advanced.dox.txt index b2b77b5de..c3af0c372 100644 --- a/src/doc/manual/k-chan_struct_advanced.dox.txt +++ b/src/doc/manual/k-chan_struct_advanced.dox.txt @@ -116,7 +116,7 @@ We can now discuss freely how one creates a `Msg_out`. You already know about ` @note A message *instance* is created internally by `struc::Channel` at receipt time. By the time you get the `Msg_in_ptr` into your code, it's already in existence, and it will go out of existence when that `shared_ptr = Msg_in_ptr`'s shared-pointer group reaches ref-count-zero. -Formally speaking the backing (SHM versus heap; plus config) of any given `Msg_out` is controlled via the formal concepts ipc::transport::struc::Struct_builder and ipc::transport::struc::Struct_builder::Config (and the deserialization counterparts ipc::transport::struc::Struct_reader and ipc::transport::struc::Struct_reader::Config). You can read all about them and their impls -- or even potentially how to create your own for truly advanced fanciness -- by following those links into the Reference and going from there. (In that case you will also need to understand `struc::Channel` non-tag constructor form as well as the related `Struct_builder_config` and `Struct_reader_config` class template paramers which match `Struct_builder::Config` and `Struct_reader::Config` concepts repsectively.) Here in the guided Manual we won't get into it to that level of formality and depth. We strive to keep it immediately useful but nevertheless sufficiently advanced for most needs. +Formally speaking the backing (SHM versus heap; plus config) of any given `Msg_out` is controlled via the formal concepts ipc::transport::struc::Struct_builder and ipc::transport::struc::Struct_builder::Config (and the deserialization counterparts ipc::transport::struc::Struct_reader and ipc::transport::struc::Struct_reader::Config). You can read all about them and their impls -- or even potentially how to create your own for truly advanced fanciness -- by following those links into the Reference and going from there. (In that case you will also need to understand `struc::Channel` non-tag constructor form as well as the related `Struct_builder_config` and `Struct_reader_config` class template parameters which match `Struct_builder::Config` and `Struct_reader::Config` concepts repsectively.) Here in the guided Manual we won't get into it to that level of formality and depth. We strive to keep it immediately useful but nevertheless sufficiently advanced for most needs. So here are the relevant recipes with all currently available types of message backing. Let's start with the simplest one: **heap-backed messages**. From a83a90fe720e9a304bfceb728906fc12032916dd Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:23:02 -0400 Subject: [PATCH 29/63] spelling: possibilities Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/g-session_app_org.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/g-session_app_org.dox.txt b/src/doc/manual/g-session_app_org.dox.txt index 549281ea2..8aa76e79b 100644 --- a/src/doc/manual/g-session_app_org.dox.txt +++ b/src/doc/manual/g-session_app_org.dox.txt @@ -133,7 +133,7 @@ Let's have a (singleton, really) `class Process {}` just to bracket things nicel Whatever you do store should be listed in `Process { private: }` section first, as subsequent data items will need them. -Now it's time to set up some session(s). The more difficult task is on the server side; let us assume you do need to support multiple sessions concurrently. In this discussion we will assume your application's main loop is single-threaded. Your process will need a main-loop thread, and we will continue to assume the same proactor-pattern-with-Flow-IPC-internally-starting-threads-as-needed pattern as we have been (see @ref async_loop for discussion including other possiblities). In this example I will use the `flow::async` API (as stated in the afore-linked Manual page, direct boost.asio use is similar, just with more boiler-plate). So, something like the following would work. Note we use the techniques explained in @ref session_setup (and, to a lesser extent, @ref chan_open), but now in the context of our recommended organization of the program. +Now it's time to set up some session(s). The more difficult task is on the server side; let us assume you do need to support multiple sessions concurrently. In this discussion we will assume your application's main loop is single-threaded. Your process will need a main-loop thread, and we will continue to assume the same proactor-pattern-with-Flow-IPC-internally-starting-threads-as-needed pattern as we have been (see @ref async_loop for discussion including other possibilities). In this example I will use the `flow::async` API (as stated in the afore-linked Manual page, direct boost.asio use is similar, just with more boiler-plate). So, something like the following would work. Note we use the techniques explained in @ref session_setup (and, to a lesser extent, @ref chan_open), but now in the context of our recommended organization of the program. ~~~ class Process : // In session-server app A. From 9e5462922d6b5358401941bb3090dd6032fc1628 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:23:18 -0400 Subject: [PATCH 30/63] spelling: pragmatic Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 87dd91ed5..f793af7aa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -43,7 +43,7 @@ name: Flow-IPC pipeline # - All of the above but with certain run-time sanitizers (as of this writing ASAN/LSAN, UBSAN, TSAN, # and possibly clang-MSAN) enabled at build time as well. (RelWithDebInfo is a sufficient base build type # for a sanitizer-enabled build; a subset of compilers -- as opposed to all of them -- is also sufficient -# for pragamtic reasons.) +# for pragmatic reasons.) # - doc-and-release: # - Summary: 1, generate documentation from the source code (using Doxygen et al) and make it conveniently # available. 2, update GitHub Release and GitHub Pages web site automatically with any relevant info, namely @@ -75,7 +75,7 @@ name: Flow-IPC pipeline # with a side of official releases being accessible and comprehensively presented in customary ways. # - TODO: It *could* be argued that those 2 goals are related but separate, and perhaps they should be 2 separate # jobs. However, at least as of this writing, there's definite overlap between them, and combining the 2 -# makes pragamtic sense. It's worth revisiting periodically perhaps. +# makes pragmatic sense. It's worth revisiting periodically perhaps. on: # Want to merge to development tip? Should probably pass these builds/tests and doc generation first (the latter From d929e1803b8652e555e0b98f4878c9afdd750c38 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:23:35 -0400 Subject: [PATCH 31/63] spelling: proceeding Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/ex_cli.hpp | 4 ++-- test/suite/transport_test/ex_srv.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/suite/transport_test/ex_cli.hpp b/test/suite/transport_test/ex_cli.hpp index 70d29736e..168a3b4c3 100644 --- a/test/suite/transport_test/ex_cli.hpp +++ b/test/suite/transport_test/ex_cli.hpp @@ -1153,7 +1153,7 @@ TEMPLATE template void CLASS::App_session::expect_ping_and_a(size_t chan_idx, Task&& task) { - FLOW_LOG_INFO("App_session [" << this << "]: Chan A[" << chan_idx << "]: Awaiting ping before proceeeding."); + FLOW_LOG_INFO("App_session [" << this << "]: Chan A[" << chan_idx << "]: Awaiting ping before proceeding."); m_struct_chans_a[chan_idx]->expect_msg(capnp::ExBodyA::MSG_TWO, [this, chan_idx, task = std::move(task)](Msg_in_ptr_a&& msg_in) mutable { @@ -1176,7 +1176,7 @@ TEMPLATE template void CLASS::App_session::expect_pings_and_b(size_t chan_idx, Task&& task) { - FLOW_LOG_INFO("App_session [" << this << "]: Chan B[" << chan_idx << "]: Awaiting ping before proceeeding."); + FLOW_LOG_INFO("App_session [" << this << "]: Chan B[" << chan_idx << "]: Awaiting ping before proceeding."); m_struct_chans_b[chan_idx]->expect_msgs(capnp::ExBodyB::MSG_TWO, [this, chan_idx, task = std::move(task)](Msg_in_ptr_b&& msg_in) mutable { diff --git a/test/suite/transport_test/ex_srv.hpp b/test/suite/transport_test/ex_srv.hpp index 42137a2c5..bd773e087 100644 --- a/test/suite/transport_test/ex_srv.hpp +++ b/test/suite/transport_test/ex_srv.hpp @@ -1751,7 +1751,7 @@ TEMPLATE template void CLASS::App_session::expect_ping_and_b(size_t chan_idx, Task&& task) { - FLOW_LOG_INFO("App_session [" << this << "]: Chan B[" << chan_idx << "]: Awaiting ping before proceeeding."); + FLOW_LOG_INFO("App_session [" << this << "]: Chan B[" << chan_idx << "]: Awaiting ping before proceeding."); m_struct_chans_b[chan_idx]->expect_msg(capnp::ExBodyB::MSG_TWO, [this, chan_idx, task = std::move(task)](Msg_in_ptr_b&& msg_in) mutable { From 0815ae583dfed8df1c4e1a3dcb4b86fe71dc4050 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:23:48 -0400 Subject: [PATCH 32/63] spelling: programming Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/j-chan_struct.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/j-chan_struct.dox.txt b/src/doc/manual/j-chan_struct.dox.txt index d3516f6e4..e2ca38a7a 100644 --- a/src/doc/manual/j-chan_struct.dox.txt +++ b/src/doc/manual/j-chan_struct.dox.txt @@ -702,7 +702,7 @@ Chronologically: - However, if there were more logic at that point beyond what is shown in this example, then we might check for `ok == false` and return before doing anything else. After all the channel is hosed. *In fact this means, with 100% certainty, that the code at Point Y will execute soon.* We might as well put all the deinit stuff we want to do, there. -# Point Y: Suppose, indeed, `.send()` returned `ok == false`. Then this code shall ASAP. Presumably something happened on the channel's background in-traffic processing that constitutes the channel being hosed. Usually it's a graceful-close or `EPIPE` or the like. So we call `teardown()`, where we centrally handle the deinit of the channel. -If one is used to progamming in this async-I/O model -- most commonly in our world using boost.asio -- this will be familiar. It is a little odd to think of flow control this way at first, but one gets used to it. There are certainly major positives, but this "inverted flow control" could be considered a negative (which people fight in various ways -- e.g. by using micro-threads/fibers, though that has its own complexity costs). +If one is used to programming in this async-I/O model -- most commonly in our world using boost.asio -- this will be familiar. It is a little odd to think of flow control this way at first, but one gets used to it. There are certainly major positives, but this "inverted flow control" could be considered a negative (which people fight in various ways -- e.g. by using micro-threads/fibers, though that has its own complexity costs). That said, if you're using `sync_io`-pattern `struc::Channel`, these considerations go away. Nothing happens concurrently in the background, unless your own code makes it so. Yes, there is still the on-error handler; yes, `.send()` can still emit an error -- or return `false`. However there is no need to worry about the channel being fine at Point A but at Point C `.send()` returning `false`. One would "just" not get to Point B, if earlier your own on-async-wait call `(*on_active_ev_func)()` triggered the on-error handler (synchronously). Flow control becomes linear, and things don't happen suddenly in the background. Hence properly written code should be able to `assert(ok)` at Point C without fear. From 96a556450622f9ed20c3cfe0df0da27fe8ba07e3 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:23:59 -0400 Subject: [PATCH 33/63] spelling: qualitatively Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/unit_test/sanitize/tsan/suppressions_clang.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/unit_test/sanitize/tsan/suppressions_clang.cfg b/test/suite/unit_test/sanitize/tsan/suppressions_clang.cfg index d0e01ad47..7c61944d3 100644 --- a/test/suite/unit_test/sanitize/tsan/suppressions_clang.cfg +++ b/test/suite/unit_test/sanitize/tsan/suppressions_clang.cfg @@ -48,7 +48,7 @@ # the test code is (when it comes down to it) accessing std::cout concurrently from multiple threads. # Formally speaking this is documented in Flow to be allowed, in the sense that it won't lead to undefined behavior # (crashing, etc.); but also recommended-against, because concurrent access to an ostream is liable to result in -# qualtitatively unpleasant output: interleaved text, sometimes confusing formatting, etc. Indeed this is a known +# qualitatively unpleasant output: interleaved text, sometimes confusing formatting, etc. Indeed this is a known # problem as of this writing; I have noticed that during parallelization-involving tests, the logs can be # (in spots) quite unpleasant to read; and I've made a @todo to that effect (also read on). (I speculate that # my colleague is aware of it too; it just was not a top-priority concern, as the related unit tests did their From 5085c7273ae46a7d06f7eee2a548552ba9bbc9fb Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:24:07 -0400 Subject: [PATCH 34/63] spelling: quintessential Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f793af7aa..d677da018 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -270,7 +270,7 @@ jobs: - id: release conan-profile-build-type: Release conan-profile-jemalloc-build-type: Release - # Leaving no-lto at default (false); full-on-optimized-no-debug is the quentessential LTO use case. + # Leaving no-lto at default (false); full-on-optimized-no-debug is the quintessential LTO use case. - id: relwithdebinfo conan-profile-build-type: RelWithDebInfo conan-profile-jemalloc-build-type: Release From f59e8aaf48302a9f7c70ef5c3dd149376a304aa1 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:24:26 -0400 Subject: [PATCH 35/63] spelling: received Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/f-chan_open.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/f-chan_open.dox.txt b/src/doc/manual/f-chan_open.dox.txt index 7c8816c3f..8eb2b8867 100644 --- a/src/doc/manual/f-chan_open.dox.txt +++ b/src/doc/manual/f-chan_open.dox.txt @@ -213,7 +213,7 @@ On the server end, accordingly: a_session.init_handlers(...); // On-error handler (discussed separately). // `a_session` is open! - // `its_init_channels` are open! Probably, since we receivied num_structured_channels from server, we would + // `its_init_channels` are open! Probably, since we received num_structured_channels from server, we would // now upgrade that many of leading `its_init_channels` to a struc::Channel each (exercise left to reader). // Operate on `a_session` (etc.) in here, long-term, until it is hosed. From ccc65b3c0a9cb77be1586ba3a9589b7dc08f781a Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:37:20 -0400 Subject: [PATCH 36/63] spelling: receiver Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/script_interpreter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/transport_test/script_interpreter.hpp b/test/suite/transport_test/script_interpreter.hpp index 514cfda2a..55e48a15d 100644 --- a/test/suite/transport_test/script_interpreter.hpp +++ b/test/suite/transport_test/script_interpreter.hpp @@ -89,7 +89,7 @@ class Script_interpreter : * vec.push_back(std::move(some_mq_peer_unique_ptr)); // Add a slot. */ using Mq_peer_lists = std::map; - // Similar stuff here but simpler; there are only 2 variants: POSIX vs. Bipc; a Chan_bundle is both snder and rcver. + // Similar stuff here but simpler; there are only 2 variants: POSIX vs. Bipc; a Chan_bundle is both snder and receiver. template using Chan_bundle_list = std::vector>; using Chan_bundle_list_variant = std::variant, From 7dad197e15eaab00f9a0c556b18feb16245e2b58 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:35:06 -0400 Subject: [PATCH 37/63] spelling: recipient Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/ex.capnp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/transport_test/ex.capnp b/test/suite/transport_test/ex.capnp index ee8835a0a..3ce052e6c 100644 --- a/test/suite/transport_test/ex.capnp +++ b/test/suite/transport_test/ex.capnp @@ -46,7 +46,7 @@ struct ExMdt } numChansYouWant @2 :Size; - # Guy (cli or srv) filling-out the metadata, say, sets this to # of init-channels the *recepient* will want opened + # Guy (cli or srv) filling-out the metadata, say, sets this to # of init-channels the *recipient* will want opened # on its behalf. This is contrived and only for demo purposes; so in our apps we just, like, assert this value is # consistent with that. E.g., client will say "you want 3 init-channels" and then server will go, # "ah yes, indeed I was gonna open 3 init-channels." From af7e5ad52bee796c60ca5b3fa7999141cfc8c7fd Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:35:24 -0400 Subject: [PATCH 38/63] spelling: remembered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/ex_cli.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/suite/transport_test/ex_cli.hpp b/test/suite/transport_test/ex_cli.hpp index 168a3b4c3..a668a1f65 100644 --- a/test/suite/transport_test/ex_cli.hpp +++ b/test/suite/transport_test/ex_cli.hpp @@ -490,7 +490,7 @@ void CLASS::App_session::use_channels_if_ready(size_t n_chans_a, size_t n_chans_ Uptr ch; if constexpr(S_CLASSIC_ELSE_JEM) { - /* SHM-classic: Out-messages: Doesn't matter which arena; they're not rememembered by server beyond handler + /* SHM-classic: Out-messages: Doesn't matter which arena; they're not remembered by server beyond handler * (in our case). * In-messages: Server sends app-scope messages; in arena-sharing providers like SHM-classic receiver must * specify the in-messages' scope. */ @@ -499,7 +499,7 @@ void CLASS::App_session::use_channels_if_ready(size_t n_chans_a, size_t n_chans_ } else { - /* SHM-jemalloc: Out-messages: Doesn't matter which arena; they're not rememembered by server beyond handler + /* SHM-jemalloc: Out-messages: Doesn't matter which arena; they're not remembered by server beyond handler * (in our case). * In-messages: In arena-lending providers like SHM-jemalloc receiver will deserialize fine regardless of * in which (properly lent) arena sender constructed msg. From 67395d31c6bf1eb78b94ef258afeceddc6ab5a83 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:36:01 -0400 Subject: [PATCH 39/63] spelling: respectively Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/k-chan_struct_advanced.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/k-chan_struct_advanced.dox.txt b/src/doc/manual/k-chan_struct_advanced.dox.txt index c3af0c372..10fb3812a 100644 --- a/src/doc/manual/k-chan_struct_advanced.dox.txt +++ b/src/doc/manual/k-chan_struct_advanced.dox.txt @@ -116,7 +116,7 @@ We can now discuss freely how one creates a `Msg_out`. You already know about ` @note A message *instance* is created internally by `struc::Channel` at receipt time. By the time you get the `Msg_in_ptr` into your code, it's already in existence, and it will go out of existence when that `shared_ptr = Msg_in_ptr`'s shared-pointer group reaches ref-count-zero. -Formally speaking the backing (SHM versus heap; plus config) of any given `Msg_out` is controlled via the formal concepts ipc::transport::struc::Struct_builder and ipc::transport::struc::Struct_builder::Config (and the deserialization counterparts ipc::transport::struc::Struct_reader and ipc::transport::struc::Struct_reader::Config). You can read all about them and their impls -- or even potentially how to create your own for truly advanced fanciness -- by following those links into the Reference and going from there. (In that case you will also need to understand `struc::Channel` non-tag constructor form as well as the related `Struct_builder_config` and `Struct_reader_config` class template parameters which match `Struct_builder::Config` and `Struct_reader::Config` concepts repsectively.) Here in the guided Manual we won't get into it to that level of formality and depth. We strive to keep it immediately useful but nevertheless sufficiently advanced for most needs. +Formally speaking the backing (SHM versus heap; plus config) of any given `Msg_out` is controlled via the formal concepts ipc::transport::struc::Struct_builder and ipc::transport::struc::Struct_builder::Config (and the deserialization counterparts ipc::transport::struc::Struct_reader and ipc::transport::struc::Struct_reader::Config). You can read all about them and their impls -- or even potentially how to create your own for truly advanced fanciness -- by following those links into the Reference and going from there. (In that case you will also need to understand `struc::Channel` non-tag constructor form as well as the related `Struct_builder_config` and `Struct_reader_config` class template parameters which match `Struct_builder::Config` and `Struct_reader::Config` concepts respectively.) Here in the guided Manual we won't get into it to that level of formality and depth. We strive to keep it immediately useful but nevertheless sufficiently advanced for most needs. So here are the relevant recipes with all currently available types of message backing. Let's start with the simplest one: **heap-backed messages**. From 33eae547da8368748e70c81e2bcde711cdd8b4f4 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:35:32 -0400 Subject: [PATCH 40/63] spelling: response Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/j-chan_struct.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/j-chan_struct.dox.txt b/src/doc/manual/j-chan_struct.dox.txt index e2ca38a7a..1ba1a3d87 100644 --- a/src/doc/manual/j-chan_struct.dox.txt +++ b/src/doc/manual/j-chan_struct.dox.txt @@ -574,7 +574,7 @@ One thing to watch out for here is simply that cached in-messages take up RAM/re Now then: That's about unsolicited messages. *Responses* are different. Receiving a response, when no applicable response expectation has been registered via `.async_request()` or `.sync_request()`, is an error condition but *not* a channel-hosing one. (A response to `.sync_request()` received after that call timed out is just dropped; that's it. This is not what we are discussing here.) All such situations -- a response to a non-request; a response to a one-off request that has already been satisfied; a response after `.undo_expect_responses()` -- result in the following steps. The response is dropped. *If* ipc::transport::struc::Channel::set_unexpected_response_handler() is in effect, then that handler is invoked informing you of the unexpected response. Furthermore, via an internal mechanism, the sender-side of the bad response is informed of this situation as well. On *that* side: *If* ipc::transport::struc::Channel::set_remote_unexpected_response_handler() is in effect, then that handler is invoked informing you of the unexpected response sent *by you*. @par -That feature -- the local and "remote" unexpected-reponse notification -- may be useful. Informally, though, we would suggest designing a protocol in robust enough fashion to where these guys firing would be impossible. It should really, usually, be possible to lock down your protocol to avoid races or corner cases of that nature. Though, who knows? It's conceivable that it's not always so easy. Just saying: try to keep it simple. +That feature -- the local and "remote" unexpected-response notification -- may be useful. Informally, though, we would suggest designing a protocol in robust enough fashion to where these guys firing would be impossible. It should really, usually, be possible to lock down your protocol to avoid races or corner cases of that nature. Though, who knows? It's conceivable that it's not always so easy. Just saying: try to keep it simple. @par sync_io-pattern and expect-message(s) The doc header for ipc::transport::struc::sync_io::Channel::expect_msg() and @link ipc::transport::struc::sync_io::Channel::expect_msgs() .expect_msgs()@endlink explains the deal. For your convenience here, though, spoiler alert: As noted above, async-I/O `.expect_msg*()` may trigger a "burst" of cached in-message(s) being emitted via the very handler that was just given to that method; but with `sync_io` pattern this situation creates a dichotomy: An in-message being available immediately is not quite the same as one being available asynchronously later. Therefore the `sync_io`-pattern `.expect_msg*()` API features an extra out-argument. If message(s) is/are available synchronously, it/they is/are synchronously output right into that argument. (`.expect_msg()`, naturally, emits up to 1 in-message, and if 1 was indeed emitted does not register an expectation for more -- and forgets the handler, never invoking it. `.expect_msgs()` can emit multiple in-messages synchronously into a user-supplied sequence container, and even if it does so, it remembers the handler in case more arrive later.) From 2f01f452024789ed9d1945bc207650183429709d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:36:20 -0400 Subject: [PATCH 41/63] spelling: responses Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/ex_srv.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/transport_test/ex_srv.hpp b/test/suite/transport_test/ex_srv.hpp index bd773e087..d4267ec2d 100644 --- a/test/suite/transport_test/ex_srv.hpp +++ b/test/suite/transport_test/ex_srv.hpp @@ -114,7 +114,7 @@ class Ex_srv : public Ex_guy Channels_a m_struct_chans_a; Channels_b m_struct_chans_b; - // Place to save an out-request msg ID so undo_expect_responses() can be called on it to stop expecting respones. + // Place to save an out-request msg ID so undo_expect_responses() can be called on it to stop expecting responses. struc::Channel_base::msg_id_out_t m_saved_req_id_out; /* Not-very-rigorous expectations count: e.g., expect some message = ++m_expectations_a; From 93771be0564fb6c4cadfa27380964cd7c66a2224 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:35:42 -0400 Subject: [PATCH 42/63] spelling: responsibility Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/j-chan_struct.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/j-chan_struct.dox.txt b/src/doc/manual/j-chan_struct.dox.txt index 1ba1a3d87..8bcac8e8b 100644 --- a/src/doc/manual/j-chan_struct.dox.txt +++ b/src/doc/manual/j-chan_struct.dox.txt @@ -553,7 +553,7 @@ And that's it! We have pretty much used the entire essential arsenal now. That An *in-message instance* is represented by, as we've seen, a `struc::Channel::Msg_in_ptr` which is but a `shared_ptr`; while `Msg_in` is itself an instance of the ipc::transport::struc::Msg_in class template. Its basic capabilities you've already seen: `.body_root()` to get at the structured data via capnp-generated `Reader`; `ostream <<` to pretty-print a potentially-truncated un-indented version (potentially slow but okay in TRACE-logging and the like); and so on. @par -One we have not yet mentioned is: A `Native_handle` stored in the original **message** (`struc::Msg_out` a/k/a `struc::Channel::Msg_out`) can of course be obtained from the in-message instance. Use ipc::transport::struc::Msg_in::native_handle_or_null(). One subtlety to note here: unlike `Msg_out` destructor, `Msg_in` destructor will *not* close the `Native_handle` if any. What to do with this native handle (FD in POSIX parlance) is entirely your call. Do note that in POSIX/Unix/Linux this FD refers to the same resource *description* as the original sent FD from the origin process; but it is *not* the same *descriptor*. The *description* will itself be released back into the OS's resource pool no earlier than *both* the original sendable-FD and the received-FD have been closed. So: unless you want that resource to leak, it is your reponsibility to take ownership of it. Hopefully the task is made easier by the sent-message `Msg_out` (the actual **message**, not merely the **message instance** sent) guaranteeing the closure of the sendable-FD no later than `Msg_out` being destroyed... so the send-side will not be the source of the leak. +One we have not yet mentioned is: A `Native_handle` stored in the original **message** (`struc::Msg_out` a/k/a `struc::Channel::Msg_out`) can of course be obtained from the in-message instance. Use ipc::transport::struc::Msg_in::native_handle_or_null(). One subtlety to note here: unlike `Msg_out` destructor, `Msg_in` destructor will *not* close the `Native_handle` if any. What to do with this native handle (FD in POSIX parlance) is entirely your call. Do note that in POSIX/Unix/Linux this FD refers to the same resource *description* as the original sent FD from the origin process; but it is *not* the same *descriptor*. The *description* will itself be released back into the OS's resource pool no earlier than *both* the original sendable-FD and the received-FD have been closed. So: unless you want that resource to leak, it is your responsibility to take ownership of it. Hopefully the task is made easier by the sent-message `Msg_out` (the actual **message**, not merely the **message instance** sent) guaranteeing the closure of the sendable-FD no later than `Msg_out` being destroyed... so the send-side will not be the source of the leak. @par On a related note: A particular `Msg_in` (`struc::Msg_in<...>`) object represents a message *instance*. That is it represents a message *as sent and received that particular time*. A `Msg_out` can be re-sent later; and it can even be modified and re-sent (as many times as desired). We'll cover that in @ref chan_struct_advanced -- but be aware of it even now. Spoiler alert: If SHM-backing is configured (as we generally recommend), then the original `Msg_out` *and* any `Msg_in` in existence (and there can be multiple) really refer to the same RAM resource. Hence the RAM is returned for other use no sooner than all those guys have been destroyed (across all processes involved). If SHM-backing is *not* used, then each `Msg_in` is really a copy of the original, and therefore the `Msg_out` and all derived `Msg_in`s are independent, returning each RAM resource on destruction of that object. From 43b85559998de10067a82aae90ccc563c54f263d Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:35:51 -0400 Subject: [PATCH 43/63] spelling: responsible Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/g-session_app_org.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/g-session_app_org.dox.txt b/src/doc/manual/g-session_app_org.dox.txt index 8aa76e79b..25673f278 100644 --- a/src/doc/manual/g-session_app_org.dox.txt +++ b/src/doc/manual/g-session_app_org.dox.txt @@ -100,7 +100,7 @@ The Manual author(s) must stress that much of the following does not represent h The basic problem we are solving here is this: You have your algorithms and data structures, in your meta-application Ap-Bp, and in service of these it is required that you perform IPC. To perform IPC, in the ipc::session paradigm, Flow-IPC *requires* that you use its abstractions, most notably those of `Session_server`, `Server_session` (on open, just `Session`), and `Client_session` (ditto). How to organize your code given your existing algorithms/structures and the aforementioned Flow-IPC abstractions? The key point is that each of your own (IPC-relevant) data structures (and probably related algorithms) should be very cleanly and explicitly classified to have a particular *scope*, a/k/a lifetime. Generally, the scope of each (IPC-relevant) datum is one of the following: - - **[Per-]session scope**: The datum begins life no earlier than the creation of the (*opened*!) `Session` (A-B process-to-process conversation) and no later than the (opened) `Session`'s destruction. If the session ends (as earlier noted, when the process exits -- or, far more interestingly, when the *opposing* process exits or dies or gets zombified), then this datum is no longer relevant by definition: The process reponsible for ~half of the algorithm that uses the datum is simply out of commission permanently, at a minimum. + - **[Per-]session scope**: The datum begins life no earlier than the creation of the (*opened*!) `Session` (A-B process-to-process conversation) and no later than the (opened) `Session`'s destruction. If the session ends (as earlier noted, when the process exits -- or, far more interestingly, when the *opposing* process exits or dies or gets zombified), then this datum is no longer relevant by definition: The process responsible for ~half of the algorithm that uses the datum is simply out of commission permanently, at a minimum. - **Cross-session scope** a/k/a **app scope**: The datum may be accessed by possibly multiple sessions concurrently; and possibly by sessions that do not yet exist. For example, an in-memory cache of web objects might be relevant to any processes that might connect later to make use of (and add to) the cache, not to mention any processes currently connected into the IPC-engaged system. - Consider a given `Session_server`. App-scope data, if they even exist in your meta-application at all, do not simply apply to all sessions to start via this `Session_server`. Instead each cross-section datum must pertain to a particular partner (client) *application* (not process -- that'd be per-session). For example, if your server Ap supports (as listed in ipc::session::Server_app::m_allowed_client_apps) two possible partner applications Bp and Cp, then a given datum must be classified (by you) to be either per-app-B or per-app-C. - Such a datum begins life no earlier than the *first* session pertaining to the particular `Client_app` becoming open (which can occur only after `Session_server` construction). Its life ends no later than the `Session_server`'s destruction. From b8e0d39abb30f92efbe276d9d1adab11ad470b3c Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:37:26 -0400 Subject: [PATCH 44/63] spelling: sender Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/script_interpreter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/transport_test/script_interpreter.hpp b/test/suite/transport_test/script_interpreter.hpp index 55e48a15d..27ff20fc4 100644 --- a/test/suite/transport_test/script_interpreter.hpp +++ b/test/suite/transport_test/script_interpreter.hpp @@ -89,7 +89,7 @@ class Script_interpreter : * vec.push_back(std::move(some_mq_peer_unique_ptr)); // Add a slot. */ using Mq_peer_lists = std::map; - // Similar stuff here but simpler; there are only 2 variants: POSIX vs. Bipc; a Chan_bundle is both snder and receiver. + // Similar stuff here but simpler; there are only 2 variants: POSIX vs. Bipc; a Chan_bundle is both sender and receiver. template using Chan_bundle_list = std::vector>; using Chan_bundle_list_variant = std::variant, From bf35aee9512778356a6ca70e92ee43eba86a45de Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:03:41 -0400 Subject: [PATCH 45/63] spelling: shall Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/script_interpreter.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/suite/transport_test/script_interpreter.cpp b/test/suite/transport_test/script_interpreter.cpp index 43f269a6c..bd3af6509 100644 --- a/test/suite/transport_test/script_interpreter.cpp +++ b/test/suite/transport_test/script_interpreter.cpp @@ -960,7 +960,7 @@ void Script_interpreter::cmd_blob_sender_send_end_impl(const Peer_list& peers, u } }); // test_with_timeout() /* Otherwise it'll throw which shall at some point (assuming our owner is cool) gracefully destroy *this - * which shall destroy `peers` which shall shall destroy *peer (hence join its internal thread(s)). */ + * which shall destroy `peers` which shall destroy *peer (hence join its internal thread(s)). */ } // Script_interpreter::cmd_blob_sender_send_end_impl() void Script_interpreter::cmd_socket_stream_send_end() @@ -1128,7 +1128,7 @@ void Script_interpreter::cmd_socket_stream_receiver_recv_impl(const Peer_list& p } }); // test_with_timeout() /* Otherwise it'll throw which shall at some point (assuming our owner is cool) gracefully destroy *this - * which shall destroy m_test_* which shall shall destroy *peer (hence join its internal thread(s)). */ + * which shall destroy m_test_* which shall destroy *peer (hence join its internal thread(s)). */ } // Script_interpreter::cmd_socket_stream_receiver_recv_impl() void Script_interpreter::cmd_socket_stream_recv_blob() @@ -1227,7 +1227,7 @@ void Script_interpreter::cmd_blob_receiver_recv_blob_impl(const Peer_list& peers validate_rcvd_blob_contents(blob, exp_blob_n); // Throw on error. }); // test_with_timeout() /* Otherwise it'll throw which shall at some point (assuming our owner is cool) gracefully destroy *this - * which shall destroy m_test_sock_streams which shall shall destroy *sock_stm (hence join its internal thread(s)). */ + * which shall destroy m_test_sock_streams which shall destroy *sock_stm (hence join its internal thread(s)). */ } // Script_interpreter::cmd_blob_receiver_recv_blob_impl() flow::util::Blob Script_interpreter::test_blob(size_t n) const @@ -1431,7 +1431,7 @@ void Script_interpreter::cmd_socket_stream_acceptor_accept() } }); /* Otherwise it'll throw which shall at some point (assuming our owner is cool) gracefully destroy *this - * which shall destroy m_test_sock_stm_acceptors and m_test_sock_streams which shall shall destroy any + * which shall destroy m_test_sock_stm_acceptors and m_test_sock_streams which shall destroy any * added streams and `acceptor` (hence join their internal threads). */ } // Script_interpreter::cmd_socket_stream_acceptor_accept() From 7a69ef37159ee2522714ca1e92c6fb98d7b96e4b Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:03:50 -0400 Subject: [PATCH 46/63] spelling: some Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/k-chan_struct_advanced.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/k-chan_struct_advanced.dox.txt b/src/doc/manual/k-chan_struct_advanced.dox.txt index 10fb3812a..8475e181f 100644 --- a/src/doc/manual/k-chan_struct_advanced.dox.txt +++ b/src/doc/manual/k-chan_struct_advanced.dox.txt @@ -31,7 +31,7 @@ In @ref chan_struct we kept things simple: Create `struc::Channel`. Create a me However the abilities of the ipc::transport **structured layer** go beyond that basic and effective paradigm. Hand-wavily speaking, an ipc::transport::struc::Msg_out (which represents a **message**, as opposed to message instance, and is not so different conceptually from a container) can be seen as not a short-lived message -- that exists essentially just before sending and just after receiving -- but as a *data structure* whose lifetime is practically unlimited (if so desired). -It is probably clear already that capnp provides the ability to express many data structures (as ~anything can be built on top of `struct`s, `union`s, and `List`s). (Granted, things like sorted trees and hash-tables would need some some added code to be conveniently accessed directly within a capnp schema, but that is also possible.) +It is probably clear already that capnp provides the ability to express many data structures (as ~anything can be built on top of `struct`s, `union`s, and `List`s). (Granted, things like sorted trees and hash-tables would need some added code to be conveniently accessed directly within a capnp schema, but that is also possible.) @note If a native capnp schema is insufficient for your data structure's performance or semantic needs, we provide first-class-citizen support for direct C++ data structures, including STL-compliant containers, in shared memory. See @ref transport_shm. From 151460c88dda4cb23346f37ba86e073f4b603f87 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:37:39 -0400 Subject: [PATCH 47/63] spelling: source Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 44148d7d4..dc1e20909 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -152,7 +152,7 @@ and checked-in using the `ipc/` pipeline. (Search for `git push` in the two `ma We have already mentioned this above. The above steps for *locally* generating the documentation are provided only -so you can locally test soure code changes' effects on the resulting docs. +so you can locally test source code changes' effects on the resulting docs. Locally generating and verifying docs, after changing source code, is a good idea. However it's also possible (and for some people/situations preferable) to skip it. The CI/CD pipeline will mandatorily generate the docs, when a PR is created or updated, as we explained above. From 4e0fab72d17d84a94833ef56fcabb0e2fdc3113f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:37:56 -0400 Subject: [PATCH 48/63] spelling: straightforward Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be3ccdc28..92b9599ba 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ Observations (tested using decent server-grade hardware): - Also significantly more RAM might be used at points. - For very small messages the two techniques perform similarly: ~100 microseconds. -The code for this, when using Flow-IPC, is straighforward. Here's how it might look on the client side: +The code for this, when using Flow-IPC, is straightforward. Here's how it might look on the client side: ~~~cpp // Specify that we *do* want zero-copy behavior, by merely choosing our backing-session type. From e09a606fde6c9e4f3edcc138dc8a6e33fc1ace02 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:38:12 -0400 Subject: [PATCH 49/63] spelling: structure Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/b-api_overview.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/b-api_overview.dox.txt b/src/doc/manual/b-api_overview.dox.txt index 4704ce956..abc0db441 100644 --- a/src/doc/manual/b-api_overview.dox.txt +++ b/src/doc/manual/b-api_overview.dox.txt @@ -316,7 +316,7 @@ All those subleties about different types of pipes in a `Channel` bundle complet @anchor api_overview_transport_struc Transport (structured) ---------------------- -While a `Channel` transports blobs and/or native handles, it is likely the Flow-IPC user will want to be able to transmit schema-based structured data, gaining the benefits of that approach including arbitrary data-structuree complexity and forward/backward-compatibility. [capnp (Cap'n Proto)](https://capnproto.org) is the best-in-class third-party framework for schema-based structured data; ipc::transport's structured layer works by integrating with capnp. +While a `Channel` transports blobs and/or native handles, it is likely the Flow-IPC user will want to be able to transmit schema-based structured data, gaining the benefits of that approach including arbitrary data-structure complexity and forward/backward-compatibility. [capnp (Cap'n Proto)](https://capnproto.org) is the best-in-class third-party framework for schema-based structured data; ipc::transport's structured layer works by integrating with capnp. To deal with structured data instead of mere blobs (though a schema-based structure can, of course, itself store blobs such as images), one simply constructs an ipc::transport::struc::Channel, feeding it an `std::move()`d already-opened @link ipc::transport::Channel Channel@endlink. This is called **upgrading** an unstructured `Channel` to a `struc::Channel`. A key template parameter to `struc::Channel` is a capnp-generated root schema class of the user's choice. This declares, at compile-time, what data structures (messages) one can transmit via that `struc::Channel` (and an identically-typed counterpart `struc::Channel` in the opposing process). From 83b2cda45ac39ae746c1faf6ba796a0d4be12307 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:09:04 -0400 Subject: [PATCH 50/63] spelling: structures Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/h-safety_perms.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/h-safety_perms.dox.txt b/src/doc/manual/h-safety_perms.dox.txt index 35cd4c584..1919afad8 100644 --- a/src/doc/manual/h-safety_perms.dox.txt +++ b/src/doc/manual/h-safety_perms.dox.txt @@ -30,7 +30,7 @@ About safety You might note that the word we use here is **safety**, not *security*. Of course your semantic preferences may differ, but what we mean to convey is this: - **Security** is about protection from malicious code, wherever it may live. Flow-IPC deals with IPC, and IPC by definition occurs within one OS instance ("machine"), so the potential malicious code would *probably* be running within the same machine, possibly even within the same application/process being developed. - - **Safety** is about being generally safe with respect to one's data strucutures and code, so that (for example, and for example *only*): + - **Safety** is about being generally safe with respect to one's data structures and code, so that (for example, and for example *only*): - If application A wants to talk to application B, it is indeed talking to application B and not application C. - In particular, if application A talks to B and C, and (say) SHared Memory is used all around, ideally the system should segregate vaddr (virtual address) areas in such a way as to make it impossible or at least unlikely that (due to an un-malicious user-code bug, maybe buffer overflow) data meant for B ends up being read by C. (Customers might see that as *security*, but in our nomenclature it's about safety, since it's not an attack that caused the potential data breach but the vendor's own bug.) - If application B goes down, gracefully or especially ungracefully, application A should be wary of accessing resources shared (e.g., in SHared Memory -- SHM) with application B, and ideally it would know about the problem as soon as physically possible so as to limit the scope of damage in the meantime. From 0b70fd4a63126099cf46b851289d951522afd2ca Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:38:27 -0400 Subject: [PATCH 51/63] spelling: subtleties Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/b-api_overview.dox.txt | 2 +- src/doc/manual/l-transport_shm.dox.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/manual/b-api_overview.dox.txt b/src/doc/manual/b-api_overview.dox.txt index abc0db441..abc7b5f3e 100644 --- a/src/doc/manual/b-api_overview.dox.txt +++ b/src/doc/manual/b-api_overview.dox.txt @@ -311,7 +311,7 @@ All transport APIs at this layer, as well the structured layer (see below), have > chan.send_blob(...); // No problem. > ~~~ -All those subleties about different types of pipes in a `Channel` bundle completely disappear when one deals with structured-data `struc::Channel`s. They are a higher-layer abstraction and will leverage whatever `transport::Channel` it adapts. In addition to handling capnp-encoded structured data and SHM-backed zero-copy, it also provides basics like request/response, request-method multiplexing, and a bit more. So let's get into that. +All those subtleties about different types of pipes in a `Channel` bundle completely disappear when one deals with structured-data `struc::Channel`s. They are a higher-layer abstraction and will leverage whatever `transport::Channel` it adapts. In addition to handling capnp-encoded structured data and SHM-backed zero-copy, it also provides basics like request/response, request-method multiplexing, and a bit more. So let's get into that. @anchor api_overview_transport_struc Transport (structured) diff --git a/src/doc/manual/l-transport_shm.dox.txt b/src/doc/manual/l-transport_shm.dox.txt index 2fee14bf8..71149b7b7 100644 --- a/src/doc/manual/l-transport_shm.dox.txt +++ b/src/doc/manual/l-transport_shm.dox.txt @@ -370,7 +370,7 @@ Yes and no. Depends. First if `T` is a POD (as defined earlier in this Manual To recap: if it's a POD, same `T` on all sides. If it uses STL-compliant/pointer stuff, then the most generic way it to use `Session::Allocator` in owner code; `Session::Borrower_allocator` in borrower code. And if targeting SHM-classic specifically, it is *okay* -- for conciseness though not genericness -- to just use the same type `T` on both sides, period. @par -What's going on here, you ask? We'd rather not get into it here; we've provided the recipe. But various docs inside ipc::shm explain all the subleties. Long story short: SHM-classic is highly symmetric and (relatively) simple, so the borrower and owner are really internally operating on the same SHM-pool. In SHM-jemalloc only the owner even *has* the arena per se; the borrower has only a read-only view into parts of it -- so it needs a special, degenerate "borrower" allocator which is used not to *allocate* but to only interpret pointers properly. (Whereas on the owner side it is used for that *and* allocation code.) +What's going on here, you ask? We'd rather not get into it here; we've provided the recipe. But various docs inside ipc::shm explain all the subtleties. Long story short: SHM-classic is highly symmetric and (relatively) simple, so the borrower and owner are really internally operating on the same SHM-pool. In SHM-jemalloc only the owner even *has* the arena per se; the borrower has only a read-only view into parts of it -- so it needs a special, degenerate "borrower" allocator which is used not to *allocate* but to only interpret pointers properly. (Whereas on the owner side it is used for that *and* allocation code.) --- From eb49c440dd2f5d8d57b05a148ef6d15e9fd4da91 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:38:43 -0400 Subject: [PATCH 52/63] spelling: successfully Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/f-chan_open.dox.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/manual/f-chan_open.dox.txt b/src/doc/manual/f-chan_open.dox.txt index 8eb2b8867..ca199de5c 100644 --- a/src/doc/manual/f-chan_open.dox.txt +++ b/src/doc/manual/f-chan_open.dox.txt @@ -269,7 +269,7 @@ Quick snippets to demonstrate follow. Here we chose the session-client as the p // Thread U. auto new_channel = std::move(*new_channel_ptr); - // It's ready: the other side successfuly invoked session.open_channel(). + // It's ready: the other side successfully invoked session.open_channel(). // Use it. E.g., upgrade it to struc::Channel, or not, then send/receive stuff. go_do_ipc_yay(std::move(new_channel)); }); @@ -319,7 +319,7 @@ We've covered pretty much every approach for opening channels via ipc::session. // Fish out the metadata. const bool do_upgrade_to_struct_chan = chan_open_mdt->getPayload().getDoUpgradeToStructuredChannel(); - // It's ready: the other side successfuly invoked session.open_channel(). + // It's ready: the other side successfully invoked session.open_channel(). // Use it. E.g., upgrade it to struc::Channel, or not -- based on `do_upgrade_to_struct_chan`. go_do_ipc_yay(std::move(new_channel), do_upgrade_to_struct_chan); }); From 34b97fc5c09cf4454c2a75c9e58d054237971a62 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:38:50 -0400 Subject: [PATCH 53/63] spelling: suppressions Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d677da018..56f0d678f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -476,7 +476,7 @@ jobs: # test). The proper technique is: 1, which of the suppression contexts (see above) are relevant? # (Safest is to specify all contexts; as you'll see just below, it's fine if there are no files in a given # context. However it would make code tedious to specify that way everywhere; so it's fine to skip contexts where - # we know that these days there are no suppresisons.) Let the contexts' dirs be $DIR_A, $DIR_B, .... Then: + # we know that these days there are no suppressions.) Let the contexts' dirs be $DIR_A, $DIR_B, .... Then: # 2, `{ cat $DIR_A/${{ env.san-suppress-cfg-in-file1 }} $DIR_A/${{ env.san-suppress-cfg-in-file2 }} \ # $DIR_B/${{ env.san-suppress-cfg-in-file1 }} $DIR_B/${{ env.san-suppress-cfg-in-file2 }} \ # ... \ From 5dc29891adac53330700b87fef5560f2b60f0372 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:03:54 -0400 Subject: [PATCH 54/63] spelling: the Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/b-api_overview.dox.txt | 2 +- src/doc/manual/f-chan_open.dox.txt | 4 ++-- src/doc/manual/j-chan_struct.dox.txt | 2 +- src/doc/manual/k-chan_struct_advanced.dox.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/manual/b-api_overview.dox.txt b/src/doc/manual/b-api_overview.dox.txt index abc7b5f3e..8da4df913 100644 --- a/src/doc/manual/b-api_overview.dox.txt +++ b/src/doc/manual/b-api_overview.dox.txt @@ -523,7 +523,7 @@ At no point do you have to worry about naming a SHM pool, removing it from the f > Session::Structured_channel<...> chan(..., > Channel_base::S_SERIALIZE_VIA_SESSION_SHM, ...); // <-- CHANGED LINE. > // --- CHANGE TO --v -> // Now the the message can live *past* the session: until the Session_server is destroyed, meaning +> // Now the message can live *past* the session: until the Session_server is destroyed, meaning > // your process accepting incoming sessions exits. For example, suppose your session-server accepts > // (sessions) from many session-client processes of one application over its lifetime; session-client A sends > // a PutCache message containing a large file's contents to session-server which memorizes it (to serve later); diff --git a/src/doc/manual/f-chan_open.dox.txt b/src/doc/manual/f-chan_open.dox.txt index ca199de5c..5e4989bbc 100644 --- a/src/doc/manual/f-chan_open.dox.txt +++ b/src/doc/manual/f-chan_open.dox.txt @@ -54,8 +54,8 @@ The second question to answer is: Do you want to, underneath it all, use **messa (Otherwise specify `S_MQ_TYPE_OR_NONE = ipc::session::schema::MqType::NONE`.) An ipc:session-generated `Channel` contains *either one or two bidirectional pipes*; if 2 then they can be used independently of each other, one capable of transmitting blobs, the other of blobs and blob/native-handle pairs. If used directly, sans upgrade to structured messaging, you can use the pipe(s) as desired. Alternatively if a 2-pipe `Channel` is upgraded to `struc::Channel` in particular, then it will handle the pipe choice internally on your behalf. For *performance*: - - `struc::Channel` shall use the the blobs-only pipe for any message that does *not* contain (as specified by the user) a native handle. - - `struc::Channel` shall use the the blobs-and-handles pipe for any message *does* contain a native handle. + - `struc::Channel` shall use the blobs-only pipe for any message that does *not* contain (as specified by the user) a native handle. + - `struc::Channel` shall use the blobs-and-handles pipe for any message *does* contain a native handle. - `struc::Channel` shall never reorder messages (maintaining, internally, a little reassembly queue in the rare case of a race between a handle-bearing and non-handle-bearing message). All of that said, the bottom line is: diff --git a/src/doc/manual/j-chan_struct.dox.txt b/src/doc/manual/j-chan_struct.dox.txt index 8bcac8e8b..6788f5a66 100644 --- a/src/doc/manual/j-chan_struct.dox.txt +++ b/src/doc/manual/j-chan_struct.dox.txt @@ -206,7 +206,7 @@ _Tip_: Let `X` be a compound field, particularly `List`, `Text` (string/list-of- (However, if the new `n` is different from the preceding, then there is no choice but to re-`.initX()`. A list/blob/string's size cannot be modified in capnp. It is best to avoid any situation where the `n` would change; try to design your protocol differently.) @par -_Tip_: Use `ostream <<` to pretty-print a `struc::Msg_out`, without newlines/indentation and truncated as needed to a reasonable length. For fully indented pretty-printing you may use `capnp::prettyPrint(msg.body_root()->asReader()).flatten().cStr()`. (Be wary of the perf cost of such an operation, especially for large messages. Though if done within a `FLOW_LOG_*()` no evaluation occurs, unless the the log-level check passes.) +_Tip_: Use `ostream <<` to pretty-print a `struc::Msg_out`, without newlines/indentation and truncated as needed to a reasonable length. For fully indented pretty-printing you may use `capnp::prettyPrint(msg.body_root()->asReader()).flatten().cStr()`. (Be wary of the perf cost of such an operation, especially for large messages. Though if done within a `FLOW_LOG_*()` no evaluation occurs, unless the log-level check passes.) --- diff --git a/src/doc/manual/k-chan_struct_advanced.dox.txt b/src/doc/manual/k-chan_struct_advanced.dox.txt index 8475e181f..5e2634c94 100644 --- a/src/doc/manual/k-chan_struct_advanced.dox.txt +++ b/src/doc/manual/k-chan_struct_advanced.dox.txt @@ -47,7 +47,7 @@ Potentially one might also want the following property: As you will soon see, this merely requires the use of a SHM-backed serializer -- but that is already assumed at least in the default recommendation and example code in @ref chan_struct. -Finally, there is the matter of the the **lifetime** of a given `Msg_out` and associated `Msg_in`s. There are a few ways to think about this, but supposing one uses the ipc::session paradigm for channel opening (and possibly SHM use), it can be roughly described as the following capabilities: +Finally, there is the matter of the **lifetime** of a given `Msg_out` and associated `Msg_in`s. There are a few ways to think about this, but supposing one uses the ipc::session paradigm for channel opening (and possibly SHM use), it can be roughly described as the following capabilities: - a `Msg_out` (+ `Msg_in`s) lifetime that is at least equal to that of a particular ipc::session::Session; - a lifetime exceeding that of the session's. From 1e0536ffdb853cc2c99bb34aaab02238cc93f2f4 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:39:05 -0400 Subject: [PATCH 55/63] spelling: this Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/j-chan_struct.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/j-chan_struct.dox.txt b/src/doc/manual/j-chan_struct.dox.txt index 6788f5a66..233f2c019 100644 --- a/src/doc/manual/j-chan_struct.dox.txt +++ b/src/doc/manual/j-chan_struct.dox.txt @@ -100,7 +100,7 @@ A *very* central decision is the choice of `Message_body`. This is the **schema # This one we'll use to demonstrate indefinite-lifetime request... myBestShot @4 :MyBestShot; - # ...together with thise one. + # ...together with this one. } description @5 :Text; From 321711e239262c1a1ab5444733f99fbf42004da6 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:39:24 -0400 Subject: [PATCH 56/63] spelling: transmitting Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/b-api_overview.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/b-api_overview.dox.txt b/src/doc/manual/b-api_overview.dox.txt index 8da4df913..05bef00b3 100644 --- a/src/doc/manual/b-api_overview.dox.txt +++ b/src/doc/manual/b-api_overview.dox.txt @@ -611,7 +611,7 @@ Further capabilities are outside our scope here; but the main point is: At a min > } > ~~~ > -> Example of trasmitting a SHM-backed native data structure to another process follows. We transmit a handle through a capnp structured message here, but it can be done using any IPC mechanism whatsoever; even (e.g.) a file. +> Example of transmitting a SHM-backed native data structure to another process follows. We transmit a handle through a capnp structured message here, but it can be done using any IPC mechanism whatsoever; even (e.g.) a file. > > Schema which includes a native-object-in-SHM field: > ~~~{.capnp} From 2506ea9c81e6ed7c4f72d0838801ccc1810dfdc3 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:39:16 -0400 Subject: [PATCH 57/63] spelling: transport Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/perf_demo/main_cli.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/perf_demo/main_cli.cpp b/test/suite/perf_demo/main_cli.cpp index 54af16eb5..7060bce8a 100644 --- a/test/suite/perf_demo/main_cli.cpp +++ b/test/suite/perf_demo/main_cli.cpp @@ -93,7 +93,7 @@ int main(int argc, char const * const * argv) /* They already printed detailed timing info; now let's summarize the total results. As you can see it * just prints b1's RTT, b2's RTT, and the ratio; while reminding how much data was transmitted. * (Ultimately b2's RTT will always be about the same and small; whereas b1's involves a bunch of copying - * into/out of tranport and hence will be proportional to data size.) + * into/out of transport and hence will be proportional to data size.) * * The only subtlety is that we coarsen the RTT to be a multiple of 100us, rounding up. Reason: It's not * bulletproof, and it might be different on slower machines, but for now I've found this to be decent in practice: From 96a16457cf6be6677cffd183762176776a84dc81 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:39:54 -0400 Subject: [PATCH 58/63] spelling: uninitialized Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 56f0d678f..55fdef9d3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -379,7 +379,7 @@ jobs: # We concentrate on clang sanitizers; they are newer/nicer; also MSAN is clang-only. So gcc ones excluded. # Attention! Excluding some sanitizer job(s) (with these reasons): - # - MSAN: MSAN protects against reads of ununitialized memory; it is clang-only (not gcc), unlike the other + # - MSAN: MSAN protects against reads of uninitialized memory; it is clang-only (not gcc), unlike the other # *SAN. Its mission overlaps at least partially with UBSAN's; for example for sure there were a couple of # uninitialized reads in test code which UBSAN caught. Its current state -- if not excluded -- is as # follows: 1, due to (as of this writing) building dependencies, including the capnp compiler binary used From 2f1d5650c211b4add5c423efda32a78f8644f192 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:39:48 -0400 Subject: [PATCH 59/63] spelling: unrelated Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 55fdef9d3..f862c67cd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -793,7 +793,7 @@ jobs: # just to our code or 3rd party libraries but also any other stuff built # (due to setting C[XX]FLAGS in Conan profile). Targeting just the exact # stuff we want with those is hard and a separate project/ticket. - # In the meantime -fno-sanitize-recover causes completely unrealted program + # In the meantime -fno-sanitize-recover causes completely unrelated program # halts during the very-early step, when building dependencies including # capnp; some autotools configure.sh fails crazily, and nothing can work # from that point on due to dependencies-install step failing. So at this From 84ac4b754e4e9ae17c46345e305deec8df8c9b99 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:40:04 -0400 Subject: [PATCH 60/63] spelling: useful Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/transport_test/CMakeLists.txt b/test/suite/transport_test/CMakeLists.txt index ef76d0de7..fbf19642a 100644 --- a/test/suite/transport_test/CMakeLists.txt +++ b/test/suite/transport_test/CMakeLists.txt @@ -44,7 +44,7 @@ common_set_target_properties(${NAME}) # Link good ol' libipc_shm_arena_lend. target_link_libraries(${NAME} PRIVATE ipc_shm_arena_lend) -# Export (to separate directory, as there are multiple usefule files) if they `make install` or equivalent. +# Export (to separate directory, as there are multiple useful files) if they `make install` or equivalent. install(TARGETS ${NAME} RUNTIME DESTINATION bin/${NAME_ROOT}) # Our input scripts for transport_test.exec SCRIPTED mode. (One can also input one's own or even use it From 89fd577b3fafba064febd1af150b6bedc0054b8f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:40:22 -0400 Subject: [PATCH 61/63] spelling: various Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- test/suite/transport_test/README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/suite/transport_test/README.txt b/test/suite/transport_test/README.txt index 7d8e39bfa..677e2c262 100644 --- a/test/suite/transport_test/README.txt +++ b/test/suite/transport_test/README.txt @@ -6,7 +6,7 @@ transport_test.exec is an integration-test program that tests ipc::transport, ip In this mode it is an interactive(ish) tool that: - So far tests much of the *unstructured* layer (not *structured* layer) of ipc::transport. - - So far avoids any dependence on ipc::session (i.e., it establishes varius IPC pipes manually, though it does get + - So far avoids any dependence on ipc::session (i.e., it establishes various IPC pipes manually, though it does get up to the transport::Channel level (wherein various pipes are bundled together)). - Can be used at a whim to test various patterns of API use without constant laborious code editing and recompiling. - This is already achieved. I (ygoldfel) wrote it b/c testing what I wanted to test the usual way seemed painful. From 075c3167c48921d1e4ab334accd8b2d02fbd8fb1 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:40:41 -0400 Subject: [PATCH 62/63] spelling: whether Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- src/doc/manual/c-setup.dox.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/manual/c-setup.dox.txt b/src/doc/manual/c-setup.dox.txt index 39b1c3dcd..ad8d95ab3 100644 --- a/src/doc/manual/c-setup.dox.txt +++ b/src/doc/manual/c-setup.dox.txt @@ -71,7 +71,7 @@ The simplest thing to do (though, again, we do not recommend it, as it's giving The next simplest thing, and likely suitable at least for prototyping situations, is to output Flow-IPC logs to stdout and/or stderr. To do so construct a `flow::log::Simple_ostream_logger` (near the top of your application most likely), passing in the desired verbosity `enum` setting to its constructor's `Config` arg; plus `std::cout` and/or `std::cerr`. Then pass-in a pointer to this `Logger` throughout your application, when Flow-IPC requires a `Logger*` argument. Logs will go to stdout and/or stderr. (However beware that some log interleaving may occur if other parts of your application also log to the same stream concurrently -- unless they, too, use the same `Simple_ostream_logger` object for this purpose.) If your application is not based on `flow::log` (which of course is very much a possibility) then you will, longer-term, want to instead hook up your log system of choice to Flow-IPC. Don't worry: this is not hard. You need to implement the `flow::log::Logger` interface which consists of basically two parts: - - `bool should_log()` which determines whethere a given message (based on its severity `enum` and, possibly, `Component` input) should in fact be output (for example your `should_log()` might translate the input `flow::log::Sev` to your own verbosity setting and output `true` or `false` accordingly). + - `bool should_log()` which determines whether a given message (based on its severity `enum` and, possibly, `Component` input) should in fact be output (for example your `should_log()` might translate the input `flow::log::Sev` to your own verbosity setting and output `true` or `false` accordingly). - `void do_log()` which takes a pointer to the message string and metadata info (severity, file/line info among a few other things) and outputs some subset of this information as it sees fit. For example it might forward these to your own logging API -- perhaps prefixing the message with some indication it's coming from Flow-IPC. Lastly, if your application *is* based on `flow::log` -- or you would consider making it be that way -- then we'd recommend the use of `flow::log::Async_file_logger`. This is a heavy-duty file logger: it performs log writing asynchronously in a separate thread and is rotation-friendly. (It even will, optionally, capture SIGHUP itself and reopen the file, so that your rotate daemon might rename the now-completed log file, moving it out of the way and archiving it or what-not.) `Async_file_logger` is meant for heavy-duty logging (and as of this writing may be gaining more features such as gzip-on-the-fly). From eb7db700af1799aeb2a82e0d915373af36229869 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:40:47 -0400 Subject: [PATCH 63/63] spelling: workflows Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dc1e20909..164c6153f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -92,7 +92,7 @@ The master branch in each repo is called `main`. Thus any contribution will inv We have some automated CI/CD pipelines. Namely `flow`, being special as a self-contained project, has the pipeline steps in `flow/.github/workflows/main.yml` -- this is Flow's dedicated CI/CD pipeline; and `ipc`, covering Flow-IPC as an overall monolithic project, similarly has Flow-IPC's CI/CD pipeline steps in -`.github/worksflows/main.yml`. Therefore: +`.github/workflows/main.yml`. Therefore: - Certain automated build/test/doc-generation runs occur when: - creating a PR against `flow` repo; - updating that PR;