[Swan-dev] pluto: sprinkle const on many struct fd * parameters
Andrew Cagney
andrew.cagney at gmail.com
Mon Feb 24 22:00:39 UTC 2020
On Sat, 22 Feb 2020 at 13:52, D. Hugh Redelmeier <hugh at mimosa.com> wrote:
>
> | From: Andrew Cagney <andrew.cagney at gmail.com>
>
> | On Thu, 20 Feb 2020 at 17:00, D. Hugh Redelmeier <hugh at mimosa.com> wrote:
> | >
> | > | From: Andrew Cagney <andrew.cagney at gmail.com>
> | >
> | > | On Thu, 20 Feb 2020 at 15:59, D. Hugh Redelmeier <hugh at mimosa.com> wrote:
> | > | >
> | > | > | From: Andrew Cagney <andrew.cagney at gmail.com>
> | > |
> | > | > If one declares all possible struct fd * things const, the absence of
> | > | > const highlights where references could go wrong.
> | > |
> | > | Why?
> | >
> | > Those are the only places that can (directly or indirectly) change a
> | > reference count.
Here's another:
+ struct fd *const_stupidity;
+ /* global_whackfd */
+ const_stupidity = (struct fd*) (*logp)->global_whackfd;
+ (*logp)->global_whackfd = NULL;
+ close_any(&const_stupidity);
+ /* object_whackfd */
+ const_stupidity = (struct fd*) (*logp)->object_whackfd;
+ (*logp)->object_whackfd = NULL;
+ close_any(&const_stupidity);
> | I don't follow.
> |
> | I attribute the bugs in the old code to it trying to be too clever by
> | minimising the number of places that a reference needed to be taken.
>
> How so? I think that it had just the right number.
So why did it hang ...
> | This resulted in code never being sure if it needed to take a
> | reference, or free the reference because it had encountered an error.
>
> You are anthropomorphising. Some programmers didn't understand the
> discipline (it was essentially like any non-auto resource allocation
> discipline). Clearly this was not documented well enough (by me).
If you want to figure out why the old code didn't work, start here.
commit 9dc14180feb9669766686bc4b40c860eeab885a7
Author: Andrew Cagney <cagney at gnu.org>
Date: Sun Nov 3 08:20:52 2019 -0500
logging: only dup a whackfd when needed, typically when storing it
in a heap object
For instance, when copying the "global" whackfd into pending; and
copying pending's whackfd into the state. Conversely, don't dup the
wackfd when it is being passed as a parameter on the stack.
In first_pending(), explicitly release the child's old whackfd before
storing a duped new value.
In release_pending_whacks(), when ST is a CHILD SA and it's IKE SA has
a matching whackfd, release all the IKE SA's pending children (stops
whack being left haing when the child fails; the code was trying to
release the CHILD SA's pending children ...).
In flush_incomplete_child(), explictly release the child (stops extra
log messages sneaking through to whack).
This replaces "ownership transfered".
Note that it was pushed _before_ 'struct fd' - I was using
experimental struct fd code, and its reference count logging, to debug
the dup(fd). New code pulling bugs out of old code is a sure sign
that it is time to switch.
> [I'm looking at freeswan-2.06 for the following.]
>
> In Pluto, there are a bunch of global variables that conceptually have the
> scope of a single transaction (where transaction is roughly what is done
> per-event in the event loop). The macro GLOBALS_ARE_RESET was meant
> to discover some mistakes with these variables. There is a cluster
> intended for providing context for logging.
>
> whack_log_fd was one of these per-transaction globals. You've
> replaced it with a bunch of parameters.
>
> The rules for duping the FD were fairly simple. If you wished to
> preserve the fd past the current transaction, dup it (because that fd
> would be closed at the end of the transaction). When is it preserved?
Me? No.
The old code, presumably assuming things would succeed, was duping the
fd into a parameter:
- add_pending(dup_any(whack_sock), ike, c, policy, 1,
- predecessor == NULL ?
- SOS_NOBODY : predecessor->st_serialno,
- uctx);
+ add_pending(whack_sock, ike, c, policy, 1,
+ predecessor == NULL ?
+ SOS_NOBODY : predecessor->st_serialno,
+ uctx);
- initiate_connection(c->name, dup_any(st->st_whack_sock),
- empty_lmod, empty_lmod,
- NULL);
+ initiate_connection(c->name, st->st_whack_sock,
+ empty_lmod, empty_lmod,
+ NULL);
which meant, when things went wrong the callee, had to undo the
damage. I call that digging a hole.
> - on initiation of a negotiation: the negotiation will span several
> transactions and each step needs to be logged. As a useful
> side-effect, the whack command will not complete until that fd gets
> closed. The whack fd will end up in the struct state.
>
> - similar case: when a pending negotiation is recorded. The whack fd
> will end up in the pending datastructure.
>
> - analogous case: when replacing an SA.
>
> - in a continuation for opportunistic or key_add
>
> This is a lot like the discipline needed for heap string references.
>
> | The new code takes a reference when ever the pointer is copied to/from
> | the heap (or heap to heap).
> |
> | If the object is made const and we make adding references harder we
> | just encourage code that incorrectly copies the actual pointer.
>
> These are harmless unless someone casts away the const. That assumes
> that const isn't used on a declaration that isn't auto (it generally
> should not be).
> _______________________________________________
> Swan-dev mailing list
> Swan-dev at lists.libreswan.org
> https://lists.libreswan.org/mailman/listinfo/swan-dev
More information about the Swan-dev
mailing list