Currently we use the very versatile linked-list collection to store elements
with variable count. This is fine, but very inefficient: Due to the many
methods in the linked list, on 64-bit platforms an empty list alone is more
than 200 bytes. As we currently have about 50 lists per IKE_SA/CHILD_SA pair,
this takes up to 10KB just for managing the empty lists. This is about the
half of memory used by an IKE_SA/CHILD_SA pair, and obviously way too much.
The new array type is not an object, but a collection of functions on an
abstract type.
The following lists are per IKE_SA and should be considered for a replacement
with more efficient arrays (this uses load-testers on-demand created dynamic
configurations, other scenarios have different lists):
14 -> ike_sa_create() @ src/libcharon/sa/ike_sa.c:2198
10 -> auth_cfg_create() @ src/libstrongswan/credentials/auth_cfg.c:1088
6 -> task_manager_v2_create() @ src/libcharon/sa/ikev2/task_manager_v2.c:1505
6 -> proposal_create() @ src/libcharon/config/proposal.c:592
5 -> peer_cfg_create() @ src/libcharon/config/peer_cfg.c:657
4 -> child_sa_create() @ src/libcharon/sa/child_sa.c:1090
2 -> child_cfg_create() @ src/libcharon/config/child_cfg.c:536
1 -> ike_cfg_create() @ src/libcharon/config/ike_cfg.c:330
1 -> put_connected_peers() @ src/libcharon/sa/ike_sa_manager.c:854
If realloc moves an allocation, the original allocation gets freed. We
therefore must remove the hdr from the list, as it is invalid. We can add it
afterwards once it has been updated, allowing us to unlock the list during
reallocation.
If a lock is held when queue_job() is called and the same lock is
required during the destruction of a job, holding the internal lock
in the processor while calling destroy() could result in a deadlock.
Calling load() incrementally does not really work as dependencies
wouldn't be resolved properly if a required feature was to be provided
by a plugin that is loaded later with a separate call to load().
Thread-specific objects get freed when the thread value object is
destroyed (wasn't the case earlier, i.e. before 2b19dd35), which
may cause the second call to vstr_free_conf() to fail in an assert
in Vstr (depending on how it was built).
Still log an error message if critical features fail, as loaded
plugins/features are not logged in that case.
This way loaded plugins are printed before failed features and
the relation is easier to make for users. It also allows programs
to log this message on a different level.
Some static allocations in plugins won't get freed, because in the test case
process the plugins are not destroyed. If a plugin would clean up allocations
done while just using the plugin, these show up as leak in the child process,
letting tests fail.