Hi Ted,

Ted Bullock wrote on Mon, Jan 16, 2023 at 12:56:06PM -0700:

> The impetus is that the event(3) manual page isn't all that good for
> documenting how to use the library and it is missing functions that are
> included in the API and available in the shared library.

That seems true, and those are good reasons to improve the manual pages.

> Upstream of course has moved on to version 2.x, as far as I can tell
> there is no more maintenance being done on the 1.4 version

According to
  https://github.com/libevent/libevent/tree/patches-1.4
that seems accurate to me: it appears the 1.4 branch was last touched
in the git repo eight years ago, and it is marked "stale",
along with the 2.0 and 2.1 branches.

> that OpenBSD ships except the work that is done internally in the OS.

Given that our event.3 says
  .\" Copyright (c) 2000 Artur Grabowski <a...@openbsd.org>
and that the libevent git repo contains a Jurassic version
of our event.3 in the 1.4 branch and does no longer appear
to contain *any* kind of documentation in the master branch -
in particular, there is no event.3 in the master branch any longer -
i think maintaining the libevent manual pages ourselves is perfectly
fine.  I see no danger that any documentation might need to be merged
from the libevent git: it appears the libevent project regards
documentation as a useless distraction at best...  :-o

> Anyway, here is what I came up with for a few functions after reading
> the source tree. I also went back through historical releases to see
> how the API evolved over time.

I think this is likely a worthwhile project, but still needs a lot
of work before it can be considered for commit.

> I'm planning to finish off documenting the rest of the library, if
> folks have feedback, I'm interested.

Given how much feedback i have on your first file, i'm not yet reading
your second and third file right now.

We do development in steps, and the tree needs to build and be better
after each commit than before that commit.  So to be able to be committed,
your patch for the first file should also delete the now redundant
information from event.3.  Regard it as splitting one well-defined
part out of the excessively large event.3 and adding lots of missing
information while splitting it out.

> event_init.3
> ============

At this point, one line is missing:

  .\" $OpenBSD$

The command `mandoc -T lint` tells you:

  mandoc: event_init.3: STYLE: RCS id missing: (OpenBSD)

> .\" Copyright (c) 2023 Ted Bullock <tbull...@comlore.com>
> .\"
> .\" Permission to use, copy, modify, and distribute this software for any
> .\" purpose with or without fee is hereby granted, provided that the above
> .\" copyright notice and this permission notice appear in all copies.
> .\"
> .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> .\"
> .Dd $Mdocdate: January 9 2023 $
> .Dt EVENT_INIT 3
> .Os
> .Sh NAME
> .Nm event_base_new ,
> .Nm event_init

This is not nice.
Unless there is a good reason to name the page after a function that
is not the first function in the NAME section, put the function
corresponding to the file name first in NAME and in all other sections.

> .Nd initializes an
> .Vt event_base
> instance

While nesting markup inside .Nd is technically possible,
it is fragile, looks ugly, and we certainly don't do it in OpenBSD.

> .Sh SYNOPSIS
> .In event.h
> .Ft "struct event_base *"
> .Fn event_base_new void
> .Ft "struct event_base *"
> .Fn event_init void
> .Sh DESCRIPTION
> The functions
> .Fn event_base_new
> and
> .Fn event_init
> initialize the
> .Lb libevent

We don't normally use the .Lb macro in OpenBSD.
Maybe just talk about "the event library" with no markup?
The existing event.3 talks about

The
.Nm event
API ...

which is not wrong, but i'm not convinced the .Nm markup provides much
value here.

> and need to be called prior to scheduling an event or
> starting the event-loop. The two functions are similar, although global
> variables are set when calling
> .Fn event_init
> to help simplify the API for programs requiring only one event-loop.

This is not good.  Don't start comparing functions without precisely
saying first what each function actually does, in particular not in the
first sentence of a manual page.

Instead, the first sentence should only state the general purpose of
the functions documented in the page.  In this page, it might not be
needed at all, you could probably start with event_base_new(3) right
away.

After the introductory sentence(s), if any, start with one function and
document it thoroughly.  After that, document the next function.  If they
are very similar, it is sometimes useful to document the second one
relative to the first one, stating the differences, in particular if the
functions do a lot of complicated things, are very similar, the difference
is small, and the first one is more commonly used than the second on.

If both are simple, it may be better to document both stand-alone.

The order depends on various factors.
 - If one is deprecated, start with the other one.
 - If one is used a lot more than the other, start with the common one.
 - Otherwise, if at least one of them has complicated effects, start
   with the simpler one.
 - If both are quite simple, it may be better to start with the
   more general one instead and describe the simpler one as special
   case afterwards.
 - If there are no stronger reasons, start with the one naming
   the manual page.

In this case, you have to document event_base_new(3) before event_init(3)
because event_base_new(3) is a non-trivial function and event_init(3)
is merely a trivial wrapper around it.  Actually, that justifies the
order you picked for the NAME section, even though i tripped over that
quirk earlier.

> .Pp
> The
> .Lb libevent
> API is generally not thread-safe unless only one
> .Vt "event_base"
> instance is accessible per thread or care is taken to lock access.

That's way too early for saying such a thing.
Threads are not an important concept and rarely used (if at all)
in the OpenBSD base userland, so talking about them should be
relegated to the end of the DESCRIPTION, or maybe even to CAVEATS.

> .Pp
> These functions allocate memory that should be freed using

Avoid "should" in manual pages if possible.

> .Xr event_base_free 3 .

This means you have to document event_base_free(3) in the same
manual page, not in a different one.  In general, related alloc
and free functions must not be separated into different pages.

> .Pp
> Diagnostic and error messages are retrievable from these functions by
> configuring a message log callback with
> .Xr event_set_log_callback 3 .

Having this in the DESCRIPTION like this is awkward.

Instead, maybe the ERRORS section should say that the event library
usually does not set errno(2), but instead has its own system to
issue messages via callbacks, pointing to the relevant manual page.
(The exception that event_base_loop(3) does set EINTR needs to be
specifically pointed out in the ERRORS section of event_base_loop(3)
though.)

If using event_set_log_callback(3) is almost always required
when using libevent, maybe event_set_log_callback(3) should be
in the same manual page as event_init(3), such that users aren't
sent on a wild goose chase around lots of different pages.
If, on the other hand, most programs get away without using
event_set_log_callback(3), having it in a different page may be
better because it might be less distracting.

I never used libevent, so i'm not sure which is the case.
I *suspect* event_set_log_callback(3) may usually be needed
because maybe it is the only way to get any kind of diagnostics
at all, which most programs probably need - but i'm not sure.

> .Pp
> After a call to
> .Xr fork 2
> some notification methods will not persist and need to reinitiliazed with
> .Xr event_reinit 3 .

This seems misplaced.  You did not yet explain what "notification methods"
are.  If those are related to event_set_log_callback(3), maybe this
information belongs into that manual page?

> .Sh RETURN VALUES

Uh oh, end of the DESCRIPTION already?

You failed to actually say what these two functions do.

You should probably start somewhat like this:

  The function
  .Fn event_base_new
  allocates and initializes a new
  .Vt event_base
  structure    .\ or "object", if you prefer, but remain consistent
  ...

After that, it may or may not be useful to mention the most important
fields (since struct event_base is opaque, do not talk about field
names) and what they are initialized to, in particular those fields
later discussed in the context of other API functions, though for many
allocation APIs, it is not necessary to list all the fields, in particular
not those that are purely internal implementation details.

> The
> .Fn event_base_new
> and
> .Fn event_init
> functions return a
> .Vt "struct event_base"
> pointer.

Not good because that is already obvious from the prototype.
We somehow need a definite article here.
Maybe something like:

  These functions return a pointer to the newly allocated
  .Vt event_base
  structure.

Or even shorter, because it is not really ambiguous given the
prototype:

  These functions return the newly allocated
  .Vt event_base
  structure.

> If the functions fail, for example, due to a lack of memory, they do
> .Em NOT
> return.

Never use all caps in the source code for emphasis.
That serious harms accessibility because screenreaders will say

  "... they do En Oh Tee return."

Also, the content is not good enough.
It needs to say that the application program is terminated with the
exit status 1.

What a repugnant design choice, by the way...  :-(

Also, a DIAGNOSTICS section is clearly needed, listing the strings
that get passed to event_err(3) and event_errx(3) from event_base_new(3)
and explaining what they mean.

> .Sh ENVIRONMENT
> Programs using the
> .Lb libevent
> are configurable with environment variables prior to calling
> .Fn event_base_new
> or
> .Fn event_init .

That's excessively wordy, but lacks crucial information: what effects
do the *values* of those varibles have?

Maybe something like:

  Unless
  .Xr issetugid 2
  is true, the following variables are inspected.
  The values of these variables are ignored, and they take effect
  even if their value is empty or zero.

(I did not check all four variables.)

> .Bl -tag

  mandoc: event_init.3:79:2: WARNING: missing -width in -tag list

In case of doubt, say

  .Bl -tag -width Ds

> .It Ev Sy EVENT_SHOW_METHOD

The combination "Ev Sy" makes no sense.  Both are in-line macros,
and consequently, you cannot nest .Sy inside .Ev.  Instead, as
explained in the "In-line" subsection of mdoc(7), the .Sy closes
the scope of the .Ev.

Just say

  .It Ev EVENT_SHOW_METHOD

here, the all caps syntax already stands out enough without boldface.

> If the log callback is configured, report which kernel notification method the
> library is using.

This is not true for issetugid(2) programs.
The same complaint may also apply to the other environment variables.

> .It Ev Sy EVENT_NOKQUEUE
> Disable library support for
> .Xr kqueue 2

Missing full stop.

> .It Ev Sy EVENT_NOPOLL
> Disable library support for
> .Xr poll 2
> .It Ev Sy EVENT_NOSELECT
> Disable library support for
> .Xr select 2
> .El
> .Sh EXAMPLES
> In this example code a new
> .Vt "struct event_base"
> is initialized

Do not repeat the DESCRIPTION below EXAMPLES.

> with support for logging.

Maybe this example is more about logging than about new/free?
In that case, it would belong into event_set_log_callback(3)
rather than here.

> This example also applies to
> .Fn event_base_new ,
> the difference being that internal global variables are configured to simplify
> other parts of the API.

That information must go to the DESCRIPTION instead, where it is
absolutely crucial, and you must be more specific about the global
variables.  Side effects need to be carefully documented, in particular on
global variables, and even more so in functions where they are surprising,
like in _new(3) functions.

Again, what an utterly repugnant API design, but that's not your
fault.

> .Bd -literal -offset indent
> #include <stdio.h>
> #include <event.h>
> 
> void cb(int sev, const char* msg)
> {
>       printf("%d: %s\n", sev, msg);

The backslash requires escaping:

        printf("%d: %s\en", sev, msg);

> }
> 
> int main()
> {
>       event_set_log_callback(cb);
> 
>       struct event_base *base = event_init();
>       if (base == NULL) {

This does not make sense to me.
My impression is that event_base_new(3) can never return NULL,
and consequently, event_init(3) can't, either.
So testing for it not only feels useless but misleading:
it sets readers onto the wrong track and makes them misunderstand
the API - doesn't it?

>               printf("event_init failed, will not return\\n");

You almost never want to use \\ in a manual page.
Regarding the purpose of \\, see the documentation of the .de
request in the roff(7) manual page.

>               return 1;
>       }
>       /* do something with the event library here */
> 
>       event_base_free(base);
>       return 0;
> }
> .Ed
> .Sh SEE ALSO
> .Xr event_set_log_callback 3 ,
> .Xr event_base_free 3 ,
> .Xr event_dispatch 3

These need to be sorted alphabetically.

> .Sh HISTORY
> The function
> .Fn event_init
> first appeared in
> .Lb libevent-0.1

No markup here.

> although it's protoype has changed various times since that release.

Too much information, just say something like

  and uses the current prototype since ...

> In
> .Lb libevent-1.4.1beta
> .Fn event_base_new
> was added and
> .Fn event_init
> was once again changed to wrap around the new function.

Too much information, implementation details like this are not relevant
for HISTORY.  Something like

  The function
  .Fn event_base_new
  first appeared in libevent-1.4.1beta and has been available since
  .Ox ??? .

should suffice.  In general, we want to identify the OpenBSD release
first supporting a function in addition to the place and time of
original invention.

Besides, is the "beta" really needed (for example because the beta
appeared a very long time, like very many months or even several years
before the official release and was widely used by applications before
the official release)?  Wouldn't it be better to just say "first
appeared in libevent-1.4.1"?

> .Pp
> Environment variable options

That sounds like a contradiction: options and environment variables
are competing concepts and i don't think "environment variable option"
is a thing.

Maybe just something like

  Support for the environment variables first appeared in libevent-0.7a.

> first appeared in
> .Lb libevent-0.7a .

No .Lb.

> .Sh AUTHORS
> The
> .Lb libevent

Just "The event library" seems enough.

> was written by
> .An -nosplit
> .An Niels Provos
> and
> .An Nick Mathewson

Missing full stop.

> .Pp
> This manual was written by
> .An Ted Bullock Aq Mt tbull...@comlore.com

Missing full stop.

Do you want to draft a new version, taking this feedback into account?

Yours,
  Ingo

Reply via email to