Kevin Day [Wed, 29 Oct 2025 12:17:08 +0000 (07:17 -0500)]
Progress: Continue changes to locking, updating stand alone builds.
Synchronize with the FLL changes so that that stand alone builds again.
There were thread changes, including the removal of thread sets, that necessitate changing the config.h for stand alone builds.
Kevin Day [Wed, 29 Oct 2025 11:24:07 +0000 (06:24 -0500)]
Progress: Continue changes to locking.
Refactor `instance.lock` to `instance.use` to reduce the ambiguity regarding a lock named "lock".
Remove the `id` off of the instance.
This is not needed and removing it reduces the need for some locking.
The thread itself is now the "id" so `id_thread` is now renamed to just `thread`.
The `controller_instance_find()` function can now just get the instance pointer.
Add a "time" controller lock check flag.
Use this to designate expecting to return `F_time` on time outs.
Add additional documentation regarding locks.
Reduce uses of locking where possible by re-organizing code.
The `controller_instance_prepare()` function, in particular, has the the code changed to reduce how long the lock is held.
This is possible because the `controller_instance_find()` now gets the instance pointer rather than an identifier.
The `controller_instance_prepare()` function allocates the instance pointer independent of the array.
This allows for the write lock on instance to be only used when assigning to the array.
The instance must therefore be immediately freed on any error because it is not assigned to an array and cannot be auto-deallocated.
Add missing locks to areas where the locks should be, such as a read lock while reading the dependency rule status.
Make sure `instance.active` lock is set before calling `instance.use` locks (there may be more work needed regarding this).
Try to reduce how long `instance.use` are held (there may be more work needed regarding this).
Kevin Day [Sun, 21 Sep 2025 02:04:57 +0000 (21:04 -0500)]
Progress: Begin changes to locking.
I was investigating different locking change structures then I got interrupted.
I hadn't had a chance to get back to this yet and this commit is done to save the state.
These changes very likely will not work and I may end up doing this differently once I get back to this at a future date.
Kevin Day [Wed, 27 Aug 2025 02:39:33 +0000 (21:39 -0500)]
Update: Add specific source design documentation.
I have described this in one manner or another since the start of the FLL project.
This explicitly states the behavior that the FLL project (and related projects) have always followed.
Kevin Day [Fri, 15 Aug 2025 02:45:41 +0000 (21:45 -0500)]
Update: Additional lock tweaks.
I am thinking of doing some redesigning of the locking/unlocking processes after this commit.
I may end up adding a new type to the FLL project to standardize a more complex structure.
I believe I need to create a read/write lock pair with a mutex lock so that the mutex can be used to prep a lock for transitioning from a read to a write or a write to a read.
I need to do some more extensive planning.
Kevin Day [Thu, 14 Aug 2025 03:50:08 +0000 (22:50 -0500)]
Update: Add additional locking to the instance cancel.
Expand the locking functions to accept the seconds and nanoseconds.
Provide standard locking functions that do not need the seconds and nanoseconds passed.
Add locking with fail out status checks to the instance clean up function.
Kevin Day [Tue, 12 Aug 2025 02:51:13 +0000 (21:51 -0500)]
Update: Relocate the clean up thread thread cancel state.
Relocate the cancel state changes to outside both waits.
I do not like how this is now happening with a thread lock in place.
I will need to do further research and possibly further changes to better handle this.
For now, this is necessary so that when I send an interrupt signal that the clean up thread will cancel properly.
Kevin Day [Sun, 10 Aug 2025 02:22:48 +0000 (21:22 -0500)]
Bugfix: Do not use the main setting status with threads.
The signal thread and the other threads should not touch the main setting status.
Change the logic to ensure that the main setting status is left alone while threads are running.
Kevin Day [Sun, 10 Aug 2025 01:32:18 +0000 (20:32 -0500)]
Update: Major improvements in locking logic.
Major Improvements:
- Add custom thread status checking functions (also replacing `controller_thread_is_enabled()` with `controller_thread_enable_is()`).
- The thread enable property is now `enable` rather than `enabled`.
- Add new `controller_thread_enable_none_e` to allow for handling default behavior.
- Add new `enable` read/write lock to better handle the reading and writing of the enable property.
- Change the signalling logic to directly call `f_thread_condition_signal_all()` and to not read lock the conditions on signal send.
- Change the lock status checks to more explicitly check for `F_okay` so that unknown conditions without error bit set are ignored.
Being explicit on handling the `F_okay` helps ensures that the lock is guaranteed to be set.
I think I need to additional review and re-structuring of the thread logic beyond this commit.
There will likely be additional commits in the future to further improve the locking logic.
I believe that there are some cases where unlock might be called on a not-locked lock.
The additional work will likely include addressing this.
I suspect this is happening in cases where the same function is called in two different contexts.
One context is directly from a thread and another is in the middle of processing something.
The lock might not be set in the case of the directly calling from the thread.
Kevin Day [Sun, 3 Aug 2025 04:49:12 +0000 (23:49 -0500)]
Update: Thread locking and signal tweaks.
The `f_thread_condition_signal_all()` requires obtaining the mutex lock before operating.
Move this logic into a single function call and repeatedly use it to reduce code repetition.
The `controller_lock_signal()` is the function that handles the standard `f_thread_condition_signal_all()` call.
Rename `instance.wait' to `instance.wait_condition` to be more consistent.
Rename`instance.wait_lock` to `instance.wait` to be more consistent.
Add a `controller_lock_mutex()` that operates the same as `controller_lock_read()` but for a mutex lock.
The wait condition signal sender uses the newly added `controller_lock_mutex()`.
Use an inline static function `private_controller_rule_instance_perform_unlock_active()` to reduce some of the repeated `instance.active` unlocks in the function `controller_rule_instance_perform()`.
Change the cleanup thread to only unlock the `instance.lock` and `instance.action` locks when done.
I do have concerns with holding the lock before the `f_thread_join()`.
I will have to review and test this out some more.
Kevin Day [Sat, 2 Aug 2025 21:04:46 +0000 (16:04 -0500)]
Progress: Continue setup for granting init program the ability to handle shutdown/reboot.
Replace the `fll_program_standard_set_up()` call with a custom signal setup call (`controller_signal_set_up()`).
Both the init and controller programs might as well use the same signals.
The controller program should reap its own children too, even if it is not an init program.
Use a thread condition signal to communicate to the clean up thread to perform zombie reaping.
Add missing delete in the init program.
Make sure all condition signals have proper checking around the success/failure of the condition listener.
Make sure all condition broadcasts lock before sending the signal and unlocks after.
This too must be checked for success.
Send a reap condition signal to wake up the clean up thread before cancelling the instance.
Add custom thread names using recently added thread naming FLL functions.
This should make analysis and observation of threads at runtime far easier.
The clean up thread is now located sooner in the process so that the zombie reaping may be processed during entry operations.
This should allow for the init/controller programs to receive the signals.
The init program is not yet written to do anything with them yet.
I tested the serial test like this:
```
controller -s data/data/controller/example/miscellaneous/ serial
```
I noticed that the interrupt signal before the wait is reached causes the program to exit.
Once the wait is reached and an interrupt is then sent then the exit process is started before exiting.
I remember being uncertain how to handle this and left that logic to future decisions.
As of now I believe that the exit process should always be called on interrupt.
This should be addressed ideally along with this shutdown/reboot handle or at the very least immediately after that.
Kevin Day [Thu, 31 Jul 2025 02:51:02 +0000 (21:51 -0500)]
Progress: Initial setup for granting init program the ability to handle shutdown/reboot.
The standard shutdown/reboot/ctrl-alt-delete process actually operates via interrupts.
Make the init program interruptible by default and add notes in the help.
Add additional callbacks.
The help callback is added to print additional information specific to the init program.
The process thread signal is going to be a new callback that the init program can use to define custom behavior.
This custom behavior will utilize the special shutdown/reboot/ctrl-alt-delete signals.
The init program will be handling more signals than the controller program.
(I may want to consider looking into supporting more signals for the controller program as well.)
Kevin Day [Wed, 30 Jul 2025 02:42:38 +0000 (21:42 -0500)]
Bugfix: Signal thread is not cancelling when f_thread_cancel() is used.
Change the behavior to directly send the terminate signal using `f_thread_signal_write()`.
This appears to get the signal handler thread to terminate when needed.
The simulate validate mode now operates without hanging and without required a terminate signal.
Set the thread cancel state to `PTHREAD_CANCEL_ASYNCHRONOUS` while waiting for a signal.
Set the thread cancel state back to `PTHREAD_CANCEL_DEFERRED,` while not waiting for a signal.
Kevin Day [Tue, 29 Jul 2025 02:57:38 +0000 (21:57 -0500)]
Bugfix: Instance thread can deadlock on interrupt.
The instance thread can deadlock on interrupt because the thread enable is not being checked before performing the lock.
Add a wait and retry lock that includes checking if enabled.
Kevin Day [Tue, 29 Jul 2025 02:30:41 +0000 (21:30 -0500)]
Bugfix: Final clean up thread deadlocks on interrupt.
There is a sleep at the top of the while loop in the clean up thread.
This sleep does not receive interrupts when `PTHREAD_CANCEL_DEFERRED` is set as the cancel state on the thread.
Set the cancel state to `PTHREAD_CANCEL_ASYNCHRONOUS` during the execution of the loop.
This is safe because there are no special locks being held during this sleep at the top of the loop.
Restore the cancel state to `PTHREAD_CANCEL_DEFERRED` once past the sleep.
Add additional checks in the loops for `controller_thread_enabled_e` to potentially catch any situations where an immediate exit would be ideal.
Make sure all locks are unlocked before breaking out of any part of any loop.
Use a try lock when sending signals to child processes rather than a full lock to increase the chance of handling any interrupts.
Kevin Day [Sun, 6 Jul 2025 21:08:28 +0000 (16:08 -0500)]
Update: Next micro version (0.7.3).
The following are the commands that I ran to make this change:
# find data/ sources/ specifications/ documents/ licenses/ install.sh -type f -exec sed -i -e 's|0\.7\.2|0.7.3|g' -e 's|^version_micro 2|version_micro 3|g' '{}' ';'
# find sources/ -name *.h -exec sed -i -e 's|_program_version_micro_s F_string_ascii_2_s|_program_version_micro_s F_string_ascii_3_s|g' -e 's|_program_version_micro_s_length F_string_ascii_2_s_length|_program_version_micro_s_length F_string_ascii_3_s_length|g' '{}' ';'
# sed -i -e 's|version_micro 2|version_micro 3|g' data/build/settings* data/build/stand_alone/settings.*
Kevin Day [Sat, 28 Jun 2025 03:40:57 +0000 (22:40 -0500)]
Cleanup: Apply new script practices.
Be more consistent about wrapping all variables in brackets.
This helps make the code more consistent and also more compatible with other interpreters like ZSH.
Don't use echo pipe syntax and instead use "<<<" redirection pipe syntax for passing variables to program calls.
The grep commands should use either `-sho` or `-shoP`.
Kevin Day [Fri, 6 Jun 2025 02:42:16 +0000 (21:42 -0500)]
Security: Explicitly define IFS to prevent misuse.
The scripts are written with certain expectations.
This expectation may not be properly met if the `IFS` value is changed.
This can potentially be used to create some sort of exploit.
Explicitly define IFS and then do so at a local variable scope to prevent affecting the callers IFS setting.
Kevin Day [Fri, 9 May 2025 02:47:39 +0000 (21:47 -0500)]
Bugfix: Relocate static libcap linkage to after the libfll linkage.
The parameter order apparently matters when it comes to linking static libraries.
Perhaps the `-l:libXXX.a` format (instead of `-lXXX`) is where this order somehow matters.
Kevin Day [Thu, 8 May 2025 04:52:33 +0000 (23:52 -0500)]
Workaround: The compiler and linker fail to understand that compiling statically should also link statically.
This is a logic or design flaw that is just plain idiotic.
When compiling statically (passing `-static`), there cannot be any shared/dynamic linked data.
Rather than recognizing this, if there is a shared library during a static build then the shared library is linked to.
The compiler and linker, at least, supports explicitly forcing the point that a static library is to be linked.
This is done via `-l:libc.a` for libc linking rather than `-lc`.
This should not be necessary, but it unfortunately is.
Kevin Day [Thu, 1 May 2025 01:46:56 +0000 (20:46 -0500)]
Update: Next micro version (0.7.2).
The following are the commands that I ran to make this change.
# find data/ sources/ specifications/ documents/ licenses/ install.sh -type f -exec sed -i -e 's|0\.7\.1|0.7.2|g' '{}' ';'
# find data/ sources/ specifications/ documents/ licenses/ -type f -exec sed -i -e 's|^version_micro 1|version_micro 2|g' '{}' ';'
# find sources/ -name *.h -exec sed -i -e 's|_program_version_micro_s F_string_ascii_1_s|_program_version_micro_s F_string_ascii_2_s|g' '{}' ';'
# find sources/ -name *.h -exec sed -i -e 's|_program_version_micro_s_length F_string_ascii_1_s_length|_program_version_micro_s_length F_string_ascii_2_s_length|g' '{}' ';'
# sed -i -e 's|version_micro 1|version_micro 2|g' data/build/settings* data/build/stand_alone/settings.*
Kevin Day [Tue, 29 Apr 2025 22:48:39 +0000 (17:48 -0500)]
Update: Synchronize with FLL release by setting version to 0.7.1.
In the longer term the version numbers will likely be on a different number.
In the short term, as in now, it is much easier to just maintain them at the same release versions.
Kevin Day [Tue, 28 Jan 2025 04:45:43 +0000 (22:45 -0600)]
Update: Improve signal handling code.
Move the `fll_program_print_signal_received()` calls to the main program to help ensure consistent printing at the end of the program.
- Note: I am not certain if I want this instead in the main() function or not and I opted not to do so for now.
Kevin Day [Wed, 11 Sep 2024 22:32:38 +0000 (17:32 -0500)]
Security: Changes to f_memory_array_increase() API causes invalid memory access.
This is a security related regression.
The `f_memory_array_increase()` has been changed to only guarantee that at least 1 element is increased if not available.
The code is Controller is depending on the old behavior where the allocation step is guaranteed.
The new behavior of `f_memory_array_increase()` performs additional steps to prevent memory abuse which in tern causes the first allocation to only consist of a single element.
Use instead `f_memory_array_resize()` if the size is too small.
In another case, instead use `f_memory_array_increase_by()` to ensure that the increase is at least 2 elements.
Kevin Day [Wed, 31 Jul 2024 02:45:38 +0000 (21:45 -0500)]
Refactor: Change bit-wise enumerations into defines.
I did some reviewing of how the enumerations used for flags are used.
These generally are not being used as a type.
An enumeration slightly increases the resulting binary size.
Enumeration values might be limited to just type of int.
This seems like an easy (small) optimization to just use defines rather than enumerations for flags and other bit-wise numbers.
Kevin Day [Wed, 17 Jul 2024 04:21:46 +0000 (23:21 -0500)]
Progress: Add initial stand alone builds for both controller and init programs.
Bring in the stand alone build that includes the FLL source files in a build settings file.
The associated fakefile will be updated and tested later.
The config.h files are currently incomplete.
Currently to test the stand alone builds:
- Use an empty config.h file.
- Copy the sources from the monolithic FLL package into the sources directory under sources/c/fll/.
- Build the controller stand alone program via:
# fake -s data/build/stand_alone/settings.controller build
- Build the init stand alone program via:
# fake -s data/build/stand_alone/settings.init build
Due to using an empty config.h file the resulting binary is oversized due to including unneeded code.
This will change once the controller.config.h and init.config.h are appropriately updated.
Kevin Day [Wed, 17 Jul 2024 04:17:39 +0000 (23:17 -0500)]
Update: Restructure the project to make it easy to switch to or from stand alone builds, and other fixes.
Move the sources for the program to be under the program/controller directory.
This makes the structure more one to one with how it is installed.
This then makes a drop in place stand alone build easier.
Update the git ignore file:
- Add the FLL directory so that a drop in place stand alone build is unlikely to be accidentally added to this repository.
- Add the config.c and config.h to prevent accidental inclusion of local configuration source file and header file.
Fix incorrect dependencies, adding missing ones and removing non-existent ones.
Kevin Day [Tue, 16 Jul 2024 01:43:33 +0000 (20:43 -0500)]
Update: Finish migrating the project.
The project appears to work as far as basic testing and code reviewing goes.
I imagine that once I put this to regular use I will fine additional problems.
Commits after this point will be normal commits rather than migration progress commits.
Kevin Day [Fri, 12 Jul 2024 03:27:43 +0000 (22:27 -0500)]
Progress: Continue migrating the project, and do some restructuring.
Don't provide default examples as the settings.
Move all of these into an examples directory.
The examples directory is placed under a data directory that is intended to be for files such as those under the /usr/share directory.
This shows that the Featureless Make build settings specification is missing the "build_sources_data" which is a /usr/share equivalent of "-build_sources_setting" (aka /etc).
Kevin Day [Thu, 11 Jul 2024 05:48:49 +0000 (00:48 -0500)]
Progress: Continue migrating the project, updating documentation and fixing some bugs.
Update the specifications and documentation.
Drop the "/var" default in "/var/run" to just be "/run".
This is nice and newer systems are following this.
The process flags should actually be on a flag variable inside the process structure.
This flag variable got lost in migration and is now back.
Provide additional lock structural changes.
Make stronger attempts to re-establish the read locks.
(There will likely be more updates to follow regarding F_lock_read and F_lock_write.)
The need to release a read lock to get a write lock within the same thread is unideal.
I do not like how this is.
It has probably annoyed me in the past and it annoys me yet again.
The POSIX thread documentation man pages are quite lacking in some critical information in this area.
I will have to do a lot of research.
Maybe at some point in the future I might depend on a different threading system that is more sane.
I accidentally had the instance action lock being locked when the regular instance lock should be grabbed.
This caused the utility execution (or anything that executes based on a PID file) to just sit there after the first run.
This is a migration mistake that is now fixed.
I did notice that on PID file error this thread still does not exit but the 0.6 version does exit.
This is likely another migration bug that needs to be fixed.
Or this is a problem resulting from adding the F_lock_read and F_lock_write return values without getting the time to go and have the callers expect this return result.
Add some new functions for returning a pointer so that I can make the pointer a constant in the execute functions.
Kevin Day [Tue, 9 Jul 2024 04:13:43 +0000 (23:13 -0500)]
Progress: Continue migrating the project, possibly wrapping up the migration.
Additional review and tests are still required but this fixes some additional problems encountered during testing.
Try to improve grammar by treating special variables as proper nouns, such as Entry, Exit, Rule, Item, etc...
Move the environment map onto the Instance.
I decided not to put it on the cache but I might change my mind as this is being added for cache purposes.
This should help reduce repeated allocations on every execute.
I may want to add features to the Controller program to better control when to clear or deallocate memory for more security at the cost of resources and performance.
This would allow for post-compile-time configuration.
A mistake exposed a lack of error reporting for when Items is an empty array.
Add controller_print_error_rule_item_execute_none() to account for this.
The bug is that "object" and "content" in controller_rule_parameters_read() are actually optional.
I was returning a parameter error when these were not defined.
Reduce the local allocation of f_state_t and pass it along as a parameter.
These particular functions should be being called sequentially and should be able to safely pass along the state between them.
The settings for the IKI read state is temporarily modified as appropriate and then restored when finished.
Don't assign enabled variable on lock failure to avoid potential race condition.
Kevin Day [Mon, 8 Jul 2024 00:42:31 +0000 (19:42 -0500)]
Progress: Continue migrating the project, getting close to wrapping up migration.
The program appears to run and work for simple scripts.
I have not done an extensive code review.
I have not done an extensive runtime test.
This reduces the small allocation down from 16 to 8 which shows a closer allocation level to that of the 0.6 version of Controller.
The number of allocations is still fewer even with this change, so that is real good.
Add some missing code and handle other problems such as allocation problems.
An incorrect lock is being used on the execution.
I need to look out for other accidental lock migration mistakes.
This performs the time calculation changes that I recently added as a separate commit in the 0.6 version of Controller.
Kevin Day [Sat, 6 Jul 2024 23:58:47 +0000 (18:58 -0500)]
Progress: Continue migrating the project, addressing instances double-pointer.
I forgot that instances is a double-pointer.
Adjust the code to ensure that the double-pointer is handled and that the locks are allocated and de-allocated.
Add additional comments regarding things that need to be done.
Kevin Day [Wed, 3 Jul 2024 04:56:55 +0000 (23:56 -0500)]
Cleanup: Add time based version in each of the documentation and specification files where it is missing.
I am just setting the current date rather than trying to figure out the date of last change.
I also noticed that the documents/time.txt file has an incorrect license specified.
The original files from the 0.6 and 0.7 branches of the FLL project already show the open-standard-license-1.0-or-later as the license.
Make sure the documents/time.txt correctly identifies the license as open-standard-license-1.0-or-later to avoid confusion.