Synchronize the examples, the license files, the documentations, and the specifications.
Fix some problems.
I noticed that the example utility is not working as expect and so there will be more migration commits once I identify and solve this problem.
Written by Kevin Day.
.SH COPYRIGHT
.PP
-Copyright \(co 2007-2023 Kevin Day, GNU LGPL Version 2.1 or later.
+Copyright \(co 2007-2024 Kevin Day, GNU LGPL Version 2.1 or later.
Written by Kevin Day.
.SH COPYRIGHT
.PP
-Copyright \(co 2007-2023 Kevin Day, Open Standard License 1.0 or later.
+Copyright \(co 2007-2024 Kevin Day, Open Standard License 1.0 or later.
Written by Kevin Day.
.SH COPYRIGHT
.PP
-Copyright \(co 2007-2023 Kevin Day, Open Standard License 1.0 or later.
+Copyright \(co 2007-2024 Kevin Day, Open Standard License 1.0 or later.
Written by Kevin Day.
.SH COPYRIGHT
.PP
-Copyright \(co 2007-2023 Kevin Day, Open Standard License 1.0 or later.
+Copyright \(co 2007-2024 Kevin Day, Open Standard License 1.0 or later.
Written by Kevin Day.
.SH COPYRIGHT
.PP
-Copyright \(co 2007-2023 Kevin Day, Open Standard License 1.0 or later.
+Copyright \(co 2007-2024 Kevin Day, Open Standard License 1.0 or later.
Written by Kevin Day.
.SH COPYRIGHT
.PP
-Copyright \(co 2007-2023 Kevin Day, Open Standard License 1.0 or later.
+Copyright \(co 2007-2024 Kevin Day, Open Standard License 1.0 or later.
--- /dev/null
+# fss-0005
+#
+# A very basic boot process.
+#
+
+settings:
+ pid ready
+ show init
+
+ control init.socket
+ control_user 0
+ control_group 0
+ control_mode ug+rwx,o-rwx
+
+task:
+ reboot system reboot
+ shutdown system shutdown
+
+main:
+ timeout start 7
+ timeout stop 7
+ timeout kill 3
+
+ failsafe maintenance
+
+ item boot
+ item net
+ item time
+ item keyboard
+ item console
+
+boot:
+ start boot root require
+ start boot proc asynchronous require
+ start boot devices asynchronous require
+ start boot file_system asynchronous
+ start boot modules wait
+
+ start service logger
+ start service dbus asynchronous
+
+ ready
+
+net:
+ start net all asynchronous
+
+time:
+ start task clock asynchronous
+
+keyboard:
+ start task keyboard asynchronous
+
+console:
+ start service mouse asynchronous
+
+ start terminal two asynchronous
+ start terminal three asynchronous
+ start terminal four asynchronous
+ start terminal one require wait
+
+maintenance:
+ #execute /bin/agetty -8 -i -J tty1 linux
+ #execute /bin/setsid -c /bin/bash --login
+ execute /bin/bash --login
--- /dev/null
+# fss-0005
+#
+# A boot to bash process.
+#
+
+settings:
+ pid disable
+ show init
+
+main:
+ #execute /bin/agetty -8 -i -J tty1 linux
+ #execute /bin/setsid -c /bin/bash --login
+ execute /bin/bash --login
--- /dev/null
+# fss-0005
+
+settings:
+ mode helper
+
+main:
+ start program chromium asynchronous
--- /dev/null
+# fss-0005
+
+settings:
+ mode helper
+
+main:
+ start program eclipse asynchronous
--- /dev/null
+# fss-0005
+
+settings:
+ mode helper
+
+main:
+ start program firefox asynchronous
--- /dev/null
+# fss-0005
+
+settings:
+ mode program
+
+main:
+ start setup cgroups
--- /dev/null
+# fss-000d
+
+settings:
+ name "Run Chromium"
+ cgroup existing user.slice/user-1000.slice/user@1000.service/user_you/group/browser
+
+command:
+ start chromium --disable-features=UserAgentClientHint
--- /dev/null
+# fss-000d
+
+settings:
+ name "Run Eclipse"
+ cgroup existing user.slice/user-1000.slice/user@1000.service/user_you/group/eclipse
+
+command:
+ start eclipse
--- /dev/null
+# fss-000d
+
+settings:
+ name "Run Firefox (ESR)"
+ cgroup existing user.slice/user-1000.slice/user@1000.service/user_you/group/browser
+
+command:
+ start firefox-esr
--- /dev/null
+# fss-000d
+#
+# A cgroups2 example for systemd-based system using example user with example subdirectories and example programs.
+#
+# This uses a 12-core system as an example.
+#
+# This is intended to be run as the user rather than as root.
+#
+# Example sizes:
+# For 2GB: 2 * 1024 * 1024 * 1024.
+#
+
+settings:
+ name "Setup Cgroups for User 1000, named "you""
+
+script:
+
+ start {
+ main() {
+ local user="you"
+ local group="you"
+ local path_cgroup="/sys/fs/cgroup/"
+ local path_slice_1="${path_cgroup}user.slice/"
+ local path_slice_2="${path_slice_1}user-1000.slice/"
+ #local path_slice_3="${path_slice_2}" # Some systemd's might work without the service directory.
+ local path_slice_3="${path_slice_2}user@1000.service/" # Some systemd's only give access to this service directory (the '@' is a problem and requires quoting).
+ local path_user="${path_slice_3}user_${user}/"
+ local path_group="${path_user}group/"
+ local path_top_subtree="${path_cgroup}cgroup.subtree_control" # Modifying this likely requires root privileges.
+ local directories="browser eclipse untrusted"
+ local d=
+ local i=
+ local subtree="+cpu +cpuset +memory +pids"
+
+ # The user path is for restricting the user and should not grant permissions to user other than read and execute directory.
+ if [[ ! -d "${path_user}" ]] ; then
+ mkdir -p "${path_user}"
+
+ if [[ $? -ne 0 ]] ; then echo "Failed mkdir ${path_user}." ; return 1 ; fi
+ fi
+
+ chmod -R u+rwX,g+rX-w,o-rwx "${path_user}" &&
+ chgrp -R ${group} "${path_user}"
+
+ if [[ $? -ne 0 ]] ; then echo "Failed mkdir ${path_group}." ; return 1 ; fi
+
+ # The group path is for the user to restrict processes they run and must have ownership with write access.
+ if [[ ! -d "${path_group}" ]] ; then
+ mkdir -p "${path_group}"
+
+ if [[ $? -ne 0 ]] ; then echo "Failed mkdir ${path_group}." ; return 1 ; fi
+ fi
+
+ # Must have common ancestor with write acces, so fix setup from systemd to work with this one.
+ chmod -R u+rw+X,g+rX-w,o-rwx "${path_group}" &&
+ chown -R ${user}:${group} "${path_group}"
+
+ if [[ $? -ne 0 ]] ; then echo "Failed change permission on ${path_group}." ; return 1 ; fi
+
+ # Make sure the user can manipulate subtrees (May fail if any path outside of ${path_slice_1} lacks things wanted by ${subtree}).
+ echo ${subtree} >> "${path_slice_1}cgroup.subtree_control"
+ if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_1}cgroup.subtree_control." ; return 1 ; fi
+
+ echo ${subtree} >> "${path_slice_2}cgroup.subtree_control"
+ if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_2}cgroup.subtree_control." ; return 1 ; fi
+
+ echo ${subtree} >> "${path_slice_3}cgroup.subtree_control"
+ if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_3}cgroup.subtree_control." ; return 1 ; fi
+
+ echo ${subtree} >> "${path_slice_4}cgroup.subtree_control"
+ if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_slice_4}cgroup.subtree_control." ; return 1 ; fi
+
+ echo ${subtree} >> "${path_user}cgroup.subtree_control"
+ if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_user}cgroup.subtree_control." ; return 1 ; fi
+
+ echo ${subtree} >> "${path_group}cgroup.subtree_control"
+ if [[ $? -ne 0 ]] ; then echo "Failed populate subtree of ${path_group}cgroup.subtree_control." ; return 1 ; fi
+
+ for d in ${directories} ; do
+ i="${path_group}${d}/"
+
+ if [[ ! -d ${i} ]] ; then
+ echo "Creating cgroup directory '${i}'."
+
+ mkdir -p "${i}" &&
+ chown -R ${user}:${group} "${i}" &&
+ chmod -R u+rw+X,g+rX-w,o-rwx "${i}" &&
+ chmod g+s "${i}"
+
+ if [[ $? -ne 0 ]] ; then echo "Failed change permission on ${i}." ; return 1 ; fi
+ fi
+
+ if [[ ${d} == "browser" ]] ; then
+ put_into "7516192768" "${i}memory.high" &&
+ put_into "8589934592" "${i}memory.max" &&
+ put_into "3-6" "${i}cpuset.cpus"
+ elif [[ ${d} == "eclipse" ]] ; then
+ put_into "3758096384" "${i}memory.high" &&
+ put_into "4294967296" "${i}memory.max" &&
+ put_into "5-8" "${i}cpuset.cpus"
+ else
+ put_into "858993459" "${i}memory.high" &&
+ put_into "1073741824" "${i}memory.max" &&
+ put_into "9-11" "${i}cpuset.cpus"
+ fi
+
+ if [[ $? -ne 0 ]] ; then echo "Failed to restrictions for ${d} at ${i}." ; return 1 ; fi
+ done
+
+ return 0
+ \}
+
+ put_into() {
+ if [[ -e ${2} ]] ; then
+ echo ${1} > ${2} || return 1
+ fi
+
+ return 0
+ \}
+
+ main
+ }
--- /dev/null
+# fss-0005
+
+main:
+ start serial s_1 asynchronous
+ start serial s_2 asynchronous
+ start serial s_3 asynchronous
+ start serial s_4 asynchronous
+ start serial s_5 asynchronous
+ start serial s_6 asynchronous
+
+ ready wait
--- /dev/null
+# fss-0005
+
+settings:
+ mode program
+
+main:
+ ready
+
+ consider asynchronous sleep_8 asynchronous
+ consider asynchronous sleep_10 asynchronous
+
+ start asynchronous sleep_1 asynchronous
+ start asynchronous sleep_2 asynchronous
+ start asynchronous sleep_3 asynchronous
+ start asynchronous sleep_5 asynchronous
+ start asynchronous sleep_8 asynchronous
+ start asynchronous sleep_10 asynchronous
--- /dev/null
+# fss-0005
+
+settings:
+ mode program
+
+main:
+ start delay short
+ start delay long
--- /dev/null
+# fss-0005
+
+settings:
+ mode service
+
+main:
+ start delay short
+ start delay long
--- /dev/null
+# fss-0005
+
+settings:
+ mode program
+
+main:
+ start environment default
+ start environment exported
+ start environment empty
+ start environment exporting
+ start environment fake-nothing
+ start environment fake-something
+
+ start print newline
--- /dev/null
+# fss-0005
+#
+# This example shows how htop can be started during the exit process rather than the entry.
+# See the htop-alternate.exit example.
+
+settings:
+ mode program
+
+ control htop.socket
+ control_user 0
+ control_group 0
+ control_mode ug+rwx,o-rwx
+
+main:
+ start serial s_1 asynchronous
+ start serial s_2 asynchronous
+ start serial s_3 asynchronous
+
+ ready wait
--- /dev/null
+# fss-0005
+
+settings:
+ mode program
+
+ control htop.socket
+ control_user 0
+ control_group 0
+ control_mode ug+rwx,o-rwx
+
+main:
+ start command htop
--- /dev/null
+# fss-0005
+
+settings:
+ mode program
+
+ control htop.socket
+ control_user 0
+ control_group 0
+ control_mode ug+rwx,o-rwx
+
+main:
+ failsafe start_top
+
+ start serial s_1 asynchronous require
+ start serial s_2 asynchronous require
+ start serial s_3 asynchronous require
+
+ ready wait
+
+ execute htop
+
+start_top:
+ execute top
--- /dev/null
+# fss-0005
+
+settings:
+ mode program
+
+main:
+ ready
+
+ start script iki
--- /dev/null
+# fss-0005
+
+settings:
+ mode program
+
+main:
+ start serial s_1
+ start serial s_2
+ start serial s_3
+ start serial s_4
+ start serial s_5
+ start serial s_6
+
+ ready
--- /dev/null
+# fss-0005
+
+main:
+ consider serial s_1
+ consider serial s_2
+ consider serial s_3
+ consider serial s_4
+ consider serial s_5
+
+ start serial s_6
+
+ ready
--- /dev/null
+# fss-0005
+
+main:
+ timeout start 7
+ timeout stop 7
+ timeout kill 3
+
+ failsafe explode
+
+ start service sshd
+
+explode:
+ start maintenance boom
--- /dev/null
+# fss-0005
+
+main:
+ timeout start 7
+ timeout stop 7
+ timeout kill 3
+
+ failsafe explode
+
+ item first
+ item last
+
+first:
+ consider script require_me
+
+ start script succeed
+ start script php
+ start command multiple
+
+ # uncomment python to see it fail.
+ #start script python
+
+last:
+ start script fail require wait
+
+explode:
+ start maintenance boom
--- /dev/null
+# fss-0005
+
+settings:
+ control controller/run/up.socket
+ pid ready
+ pid_file controller/run/up.pid
+
+main:
+ failsafe maintenance
+
+ start script create_socket_path
+
+ ready
+
+maintenance:
+ start maintenance boom
--- /dev/null
+# fss-0005
+
+main:
+ timeout start 7
+ timeout stop 7
+ timeout kill 3
+
+ failsafe explode
+
+ start utility sleeper_1
+ start utility sleeper_2
+ start utility sleeper_3
+
+explode:
+ start maintenance boom
--- /dev/null
+# fss-0005
+#
+# This example shows how htop can be started during the exit process rather than the entry.
+# See the htop-alternate.entry example.
+
+main:
+ failsafe "start top"
+
+ consider serial s_5
+ consider serial s_6
+
+ stop serial s_4 asynchronous
+ stop serial s_5 asynchronous
+ stop serial s_6 asynchronous
+
+ ready wait
+
+ execute htop
+
+start top:
+ execute top
--- /dev/null
+# fss-0005
+
+main:
+ consider serial s_1
+ consider serial s_2
+ consider serial s_3
+ consider serial s_4
+ consider serial s_5
+ consider serial s_6
+
+ stop serial s_1
+
+ ready
--- /dev/null
+# fss-0005
+
+main:
+ timeout start 7
+ timeout stop 7
+ timeout kill 3
+
+ failsafe boom
+
+ stop service sshd
+
+boom:
+ stop maintenance explode
--- /dev/null
+# fss-000d
+#
+# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
+#
+
+settings:
+ name "Sleep 1 Seconds."
+ nice 15
+ limit nice 1 2
+ on start need asynchronous sleep_10
+
+script:
+ start echo "Sleeping 1: $(date -u), depends: 10"
+
+script:
+ start sleep 1
+
+script:
+ start echo "Slept 1: $(date -u)"
--- /dev/null
+# fss-000d
+#
+# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
+#
+
+settings:
+ name "Sleep 10 Seconds."
+ nice 15
+ limit nice 1 2
+
+script:
+ start echo "Sleeping 10: $(date -u), depends: none"
+
+script:
+ start sleep 10
+
+script:
+ start echo "Slept 10: $(date -u)"
--- /dev/null
+# fss-000d
+#
+# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
+#
+
+settings:
+ name "Sleep 2 Seconds."
+ nice 15
+ limit nice 1 2
+ on start need asynchronous sleep_10
+
+script:
+ start echo "Sleeping 2: $(date -u), depends: 10"
+
+script:
+ start sleep 2
+
+script:
+ start echo "Slept 2: $(date -u)"
--- /dev/null
+# fss-000d
+#
+# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
+#
+
+settings:
+ name "Sleep 3 Seconds."
+ nice 15
+ limit nice 1 2
+ on start need asynchronous sleep_8
+
+script:
+ start echo "Sleeping 3: $(date -u), depends: 8"
+
+script:
+ start sleep 3
+
+script:
+ start echo "Slept 3: $(date -u)"
--- /dev/null
+# fss-000d
+#
+# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
+#
+
+settings:
+ name "Sleep 5 Seconds."
+ nice 15
+ limit nice 1 2
+
+script:
+ start echo "Sleeping 5: $(date -u), depends: none"
+
+script:
+ start sleep 5
+
+script:
+ start echo "Slept 5: $(date -u)"
--- /dev/null
+# fss-000d
+#
+# Note: The example setting "limit nice 1 2" may cause this rule to fail if the user has insufficient privileges granted by ulimits or some other system security measure.
+#
+
+settings:
+ name "Sleep 8 Seconds."
+ nice 15
+ limit nice 1 2
+
+script:
+ start echo "Sleeping 8: $(date -u), depends: none"
+
+script:
+ start sleep 8
+
+script:
+ start echo "Slept 8: $(date -u)"
--- /dev/null
+# fss-000d
+
+settings:
+ name "Run htop"
+
+command:
+ start htop
+
+ rerun start success delay 3000 max 3
--- /dev/null
+# fss-000d
+
+settings:
+ name "Multiple Commands: id, whoami, date, etc.."
+ capability "all="
+ control_group new memory/example
+ nice 15
+ scheduler batch 0
+ #user kevin
+ #group list 8 root
+
+ limit nofile 5000 10000
+ limit nproc 1000 2000
+ limit nice 1 2
+
+ affinity 0
+
+ on start need script require_me
+
+script:
+ start {
+ echo
+ echo "Current ulimit is"
+ ulimit -a
+ sleep 5
+
+ echo
+ echo "Current cgroup for self (PPID $PPID, PID $$) is: '$(cat /proc/self/cgroup)'"
+ sleep 5
+ }
+
+command:
+ start {
+ id
+ sleep 5
+ }
+
+script:
+ start echo
+
+command:
+ start whoami
+
+script:
+ start echo
+
+command:
+ start sleep 5
+
+command:
+ start date -u
+
+script:
+ start echo
+
+script:
+ start sleep 5
--- /dev/null
+# fss-000d
+#
+# Rule for a long delay.
+#
+
+settings:
+ name "Delay for 3 minutes."
+
+script:
+ start sleep 3m
--- /dev/null
+# fss-000d
+#
+# Rule for a short delay.
+#
+
+settings:
+ name "Delay for 3 seconds."
+
+script:
+ start sleep 3s
--- /dev/null
+# fss-000d
+#
+# Note: bash automatically creates PWD, SHLVL, and _ environment variables.
+#
+
+settings:
+ name "Environment default"
+ engine bash
+
+script:
+ start {
+ echo
+ echo "==================================="
+ echo "Environment using default settings."
+ echo "==================================="
+
+ env
+ }
--- /dev/null
+# fss-000d
+#
+# Note: bash automatically creates PWD, SHLVL, and _ environment variables.
+#
+
+settings:
+ name "Environment set to nothing"
+ environment
+ engine bash
+
+script:
+ start {
+ echo
+ echo "============================="
+ echo "Environment allowing nothing."
+ echo "============================="
+
+ env
+ }
--- /dev/null
+# fss-000d
+#
+# Note: bash automatically creates PWD, SHLVL, and _ environment variables.
+#
+
+settings:
+ name "Environment with PATH"
+ environment PATH
+ engine bash
+
+script:
+ start {
+ echo
+ echo "=========================="
+ echo "Environment allowing PATH."
+ echo "=========================="
+
+ env
+ }
--- /dev/null
+# fss-000d
+#
+# Note: bash automatically creates PWD, SHLVL, and _ environment variables.
+#
+
+settings:
+ name "Environment with PATH"
+ environment PATH custom_variable
+ engine bash
+
+script:
+ start {
+ echo
+ echo "================================="
+ echo "Exported Environment is isolated."
+ echo "================================="
+
+ export custom_variable="is not retained"
+ echo "export custom_variable='$custom_variable'"
+ echo
+ echo "Now for 'env' command:"
+ }
+
+command:
+ start env
--- /dev/null
+# fss-000d
+
+settings:
+ name "Environment using fake as an engine"
+ engine fake ++quiet
+
+ # PATH must be expoted so that "run env" works.
+ environment PATH
+
+script:
+ start {
+ settings\:
+ environment
+
+ main\:
+ print
+ print "========================================"
+ print "Environment allowing nothing using fake."
+ print "========================================"
+
+ run env
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "Environment using fake as an engine"
+ engine fake ++quiet
+
+ environment PATH PWD
+
+script:
+ start {
+ main\:
+ print
+ print "============================================="
+ print "Environment allowing PATH and PWD using fake."
+ print "============================================="
+
+ run env
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "Explosion!"
+ engine sh
+
+script:
+ start {
+ echo "kaboooom!"
+ }
+
--- /dev/null
+# fss-000d
+
+settings:
+ name "Print New Line"
+ engine bash
+
+script:
+ start echo
--- /dev/null
+# fss-000d
+
+settings:
+ name "Create Socket Path"
+
+ parameter verbose -v
+ parameter socket controller/run/
+
+script:
+ start {
+ if [[ ! -d "parameter:"socket"" ]] ; then
+ mkdir parameter:"verbose" -p parameter:"socket"
+ fi
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "Script #2"
+ on start need script succeed
+
+script:
+ start {
+ \#!/bin/bash
+ my_function() {
+ echo "Hello this is the last script, it should trigger failure."
+ return 1;
+ \}
+
+ my_function
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "IKI Variable Substitution"
+ environment PATH IKI_TEST
+ define IKI_TEST "This is iki data in an environment variable."
+ parameter some "Some Parameter Value"
+
+script:
+ start {
+ \#!/bin/bash
+ echo "====================================="
+ env
+ echo "====================================="
+ echo "IKI Path is 'define:"PATH"'"
+ echo "IKI define IKI_TEST 'define:"IKI_TEST"'"
+ echo "ENV IKI_TEST '$IKI_TEST'"
+ echo "Some Parameter is 'parameter:"some"'"
+ echo "Unknown parameter is: 'parameter:"unknown"'"
+ echo "Unknown environment is: 'define:"unknown"'"
+ echo "Unavailable environment via IKI: 'define:"USER"'"
+ echo "Unavailable environment via ENV: '$USER'"
+ echo "Program parameter verbose: 'program:"verbose"'"
+ echo "Program parameter verbose(option): 'program:"verbose:option"'"
+ echo "Program parameter verbose(value): 'program:"verbose:value"'"
+ echo "Program parameter PID: 'program:"pid"'"
+ echo "Program parameter PID(option): 'program:"pid:option"'"
+ echo "Program parameter PID(value): 'program:"pid:value"'"
+ echo "====================================="
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "PHP script"
+ environment PATH
+ engine php
+
+script:
+ start {
+ <?php
+ print("\nThis is a PHP script.\n\n");
+
+ print(date("Y/m/d h:i:s a") . "\n\n");
+
+ var_dump(getenv());
+ print("\n");
+
+ print("Now executing 'date -u' program, assuming that it exists in \$PATH.\n");
+ passthru("date -u");
+ print("\n");
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "Python (Version 3.X) script"
+ environment PATH
+ engine python3
+
+script:
+ start {
+ # Python's indentation design presents problems here and this will likely fail with "IndentationError: unexpected indent"
+ print("This is a Python script.\n");
+
+ # this is simply a design flaw of Python and as such Python scripts must not be tabbed over (making these files less readable).
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "Example script for needs, wants, and wishes."
+ environment PATH
+ engine sh
+
+script:
+ start {
+ echo
+ echo "This should be included via a need, want, or wish."
+ echo
+ }
+
--- /dev/null
+# fss-000d
+
+settings:
+ name "Script #1"
+ environment PATH
+ engine sh
+
+script:
+ start {
+ echo
+ echo "Hello this is script #1 and should succeed."
+ echo
+
+ date -u
+ echo
+ }
+
--- /dev/null
+# fss-000d
+
+settings:
+ name "Serial 1"
+ on stop need serial s_2
+
+script:
+ start {
+ echo "Serial 1: sleeping $(date -u)"
+ sleep 1
+ echo "Serial 1: slept $(date -u)"
+ }
+
+ stop {
+ echo "Serial 1: stopping, sleeping $(date -u)"
+ sleep 1
+ echo "Serial 1: stopping, slept $(date -u)"
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "Serial 2"
+ on start need serial s_1
+ on stop need serial s_3
+
+script:
+ start {
+ echo "Serial 2: sleeping $(date -u)"
+ sleep 1
+ echo "Serial 2: slept $(date -u)"
+ }
+
+ stop {
+ echo "Serial 2: stopping, sleeping $(date -u)"
+ sleep 1
+ echo "Serial 2: stopping, slept $(date -u)"
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "Serial 3"
+ on start need serial s_2
+ on stop need serial s_4
+
+script:
+ start {
+ echo "Serial 3: sleeping $(date -u)"
+ sleep 1
+ echo "Serial 3: slept $(date -u)"
+ }
+
+ stop {
+ echo "Serial 3: stopping, sleeping $(date -u)"
+ sleep 1
+ echo "Serial 3: stopping, slept $(date -u)"
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "Serial 4"
+ on start need serial s_3
+ on stop need serial s_5
+
+script:
+ start {
+ echo "Serial 4: sleeping $(date -u)"
+ sleep 1
+ echo "Serial 4: slept $(date -u)"
+ }
+
+ stop {
+ echo "Serial 4: stopping, sleeping $(date -u)"
+ sleep 1
+ echo "Serial 4: stopping, slept $(date -u)"
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "Serial 5"
+ on start need serial s_4
+ on stop need serial s_6
+
+script:
+ start {
+ echo "Serial 5: sleeping $(date -u)"
+ sleep 1
+ echo "Serial 5: slept $(date -u)"
+ }
+
+ stop {
+ echo "Serial 5: stopping, sleeping $(date -u)"
+ sleep 1
+ echo "Serial 5: stopping, slept $(date -u)"
+ }
--- /dev/null
+# fss-000d
+
+settings:
+ name "Serial 6"
+ on start need serial s_5
+
+script:
+ start {
+ echo "Serial 6: sleeping $(date -u)"
+ sleep 1
+ echo "Serial 6: slept $(date -u)"
+ }
+
+ stop {
+ echo "Serial 6: stopping, sleeping $(date -u)"
+ sleep 1
+ echo "Serial 6: stopping, slept $(date -u)"
+ }
--- /dev/null
+# fss-000d
+#
+# Example using the common sshd service.
+# Sshd appears to require a full path.
+#
+
+settings:
+ name "SSH Service"
+ nice 15
+
+service:
+ pid_file /var/run/sshd.pid
+ with full_path
+ start sshd
--- /dev/null
+# fss-000d
+# sleeper rule whose program creates its own PID file, runs in the background, sleep for a while, removes PID file, and returns.
+
+settings:
+ name "Sleeper #1"
+ nice 10
+
+utility:
+ pid_file /tmp/sleeper_1.pid
+ start {
+ \#!/bin/bash
+
+ main() {
+ if [[ -f /tmp/sleeper_1.pid ]] ; then
+ echo "Failure: pid file '/tmp/sleeper_1.pid' already exists."
+ return 1
+ fi
+
+ echo "$BASHPID" > /tmp/sleeper_1.pid
+
+ echo "Sleeper 1, now sleeping."
+ sleep 20m
+
+ echo "Sleeper 1, done sleeping."
+ rm -f /tmp/sleeper_1.pid
+ return 0
+ \}
+
+ main &
+ }
--- /dev/null
+# fss-000d
+# sleeper rule whose program creates its own PID file, runs in the background, sleep for a while, removes PID file, and returns.
+
+settings:
+ name "Sleeper #2"
+ nice 10
+
+utility:
+ pid_file /tmp/sleeper_2.pid
+ start {
+ \#!/bin/bash
+
+ main() {
+ if [[ -f /tmp/sleeper_2.pid ]] ; then
+ echo "Failure: pid file '/tmp/sleeper_2.pid' already exists."
+ return 1
+ fi
+
+ echo "$BASHPID" > /tmp/sleeper_2.pid
+
+ echo "Sleeper 2, now sleeping."
+ sleep 25m
+
+ echo "Sleeper 2, done sleeping."
+ rm -f /tmp/sleeper_2.pid
+ return 0
+ \}
+
+ main &
+ }
--- /dev/null
+# fss-000d
+# sleeper rule whose program creates its own PID file, runs in the background, sleep for a while, removes PID file, and returns.
+
+settings:
+ name "Sleeper #2"
+ nice 10
+
+utility:
+ pid_file /tmp/sleeper_3.1.pid
+ start {
+ \#!/bin/bash
+
+ main() {
+ if [[ -f /tmp/sleeper_3.1.pid ]] ; then
+ echo "Failure: pid file '/tmp/sleeper_3.1.pid' already exists."
+ return 1
+ fi
+
+ echo "$BASHPID" > /tmp/sleeper_3.1.pid
+
+ echo "Sleeper 3.1, now sleeping."
+ sleep 15
+
+ echo "Sleeper 3.1, done sleeping."
+ rm -f /tmp/sleeper_3.1.pid
+ return 0
+ \}
+
+ main &
+ }
+
+utility:
+ pid_file /tmp/sleeper_3.2.pid
+ start {
+ \#!/bin/bash
+
+ main() {
+ if [[ -f /tmp/sleeper_3.2.pid ]] ; then
+ echo "Failure: pid file '/tmp/sleeper_3.2.pid' already exists."
+ return 1
+ fi
+
+ echo "$BASHPID" > /tmp/sleeper_3.2.pid
+
+ echo "Sleeper 3.2, now sleeping."
+ sleep 20
+
+ echo "Sleeper 3.2, done sleeping."
+ rm -f /tmp/sleeper_3.2.pid
+ return 0
+ \}
+
+ main &
+ }
--- /dev/null
+# fss-000d
+#
+# Rule for initializing the /dev file system.
+#
+
+settings:
+ name "Setup /dev file system"
+
+ on start need boot root
+
+# Newer kernels automount a devpts file system on /dev, so this may not be needed.
+#command:
+# start mount /dev
+
+script:
+ start {
+ if [[ ! -d /dev/pts ]] ; then
+ mkdir /dev/pts
+ fi
+
+ if [[ ! -d /dev/shm ]] ; then
+ mkdir /dev/shm
+ fi
+
+ exit 0
+ }
+
+command:
+ start mount /dev/pts
+ stop umount -l /dev/pts
+
+command:
+ start mount /dev/shm
+ stop umount -l /dev/shm
--- /dev/null
+# fss-000d
+#
+# Rule for initializing the filesystem.
+#
+
+settings:
+ name "Setup Filesystem"
+
+ on start need boot root
+ on start need boot proc
+ on start need boot devices
+
+ on stop need boot proc
+ on stop need boot devices
+
+command:
+ start mount -n -a -O no_netdev
+ stop umount -n -arf -O no_netdev
+
+command:
+ start swapon -a
+ stop swapoff -a
+
+script:
+ start {
+ if [[ ! -d /var/run/init ]] ; then
+ mkdir /var/run/init
+ fi
+ }
--- /dev/null
+# fss-000d
+#
+# Rule for initializing the kernel modules.
+#
+
+settings:
+ name "Setup Kernel Modules"
+
+ on start need boot root
+ on start need boot proc
+ on start want boot filesystem
+
+script:
+ start {
+ if [[ ! -f /proc/modules ]] ; then
+ exit 0
+ fi
+
+ if [[ -d /modules ]] ; then
+ if [[ ! -e /modules/$(uname -r)/modules.dep ]] ; then
+ depmod
+ else
+ depmod -A
+ fi
+ fi
+
+ exit 0
+ }
--- /dev/null
+# fss-000d
+#
+# Rule for initializing the /proc filesystem.
+#
+
+settings:
+ name "Setup /proc Filesystem"
+
+ on start need boot root
+
+command:
+ start mount /proc
+
+script:
+ start {
+ if [[ -d /proc/bus/usb ]] ; then
+ mount /proc/bus/usb
+ fi
+
+ exit 0
+ }
+
+ stop {
+ if [[ -d /proc/bus/usb ]] ; then
+ umount -l /proc/bus/usb
+ fi
+
+ exit 0
+ }
--- /dev/null
+# fss-000d
+#
+# Rule for initializing the root filesystem, assuring certain directories always exist.
+#
+
+settings:
+ name "Setup Root Filesystem"
+
+command:
+ start mount -o remount,rw /
+
+script:
+ start {
+ if [[ ! -d /dev ]] ; then
+ mkdir /dev
+ fi
+
+ if [[ ! -d /dev/pts ]] ; then
+ mkdir /dev/pts
+ fi
+
+ if [[ ! -d /dev/shm ]] ; then
+ mkdir /dev/shm
+ fi
+
+ if [[ ! -d /firmware ]] ; then
+ mkdir /firmware
+ fi
+
+ if [[ ! -d /mnt ]] ; then
+ mkdir /mnt
+ fi
+
+ if [[ ! -d /modules ]] ; then
+ mkdir /modules
+ fi
+
+ if [[ ! -d /proc ]] ; then
+ mkdir /proc
+ fi
+
+ if [[ ! -d /sys ]] ; then
+ mkdir /sys
+ fi
+
+ if [[ ! -d /tmp ]] ; then
+ mkdir /tmp
+ fi
+
+ if [[ ! -d /var ]] ; then
+ mkdir /var
+ fi
+
+ if [[ ! -d /var/log ]] ; then
+ mkdir /var/log
+ fi
+
+ if [[ ! -d /var/run ]] ; then
+ mkdir /var/run
+ fi
+
+ if [[ ! -d /var/tmp ]] ; then
+ mkdir /var/tmp
+ fi
+
+ exit 0
+ }
--- /dev/null
+# fss-000d
+#
+# Rule for maintenance/failsafe console.
+#
+
+settings:
+ name "Maintenance Console"
+
+command:
+ #start setsid -c bash --login
+ start bash --login
+
+ with session
--- /dev/null
+# fss-000d
+#
+# Rule for starting all network devices.
+#
+
+settings:
+ name "System Network"
+ capability cap_net_admin=
+
+command:
+ start network start
+ stop network stop
+ restart network restart
--- /dev/null
+# fss-000d
+#
+# Rule for loopback device.
+#
+
+settings:
+ name "Loopback Device"
+
+ on start need boot modules
+
+script:
+ start {
+ ip addr add 127.0.0.1/8 label lo dev lo
+ ip link set lo up
+ }
+
+ stop {
+ ip link set lo down
+ }
--- /dev/null
+# fss-000d
+#
+# Rule for D-Bus service.
+#
+
+settings:
+ name "D-BUS"
+ capability all=
+ nice 15
+
+service:
+ pid_file /var/run/dbus/dbus.pid
+
+ start dbus-daemon --system --fork
--- /dev/null
+# fss-000d
+#
+# Rule for system logger service.
+#
+
+settings:
+ name "System Logger"
+ capability all=
+ nice 19
+ scheduler idle
+
+service:
+ # @todo consider adding support for IKI to make "/var/run/logger/logger.pid" a variable.
+ pid_file /var/run/logger/logger.pid
+
+ start metalog -B -p /var/run/logger/logger.pid -C /etc/logger.conf
--- /dev/null
+# fss-000d
+#
+# Rule for console mouse.
+#
+
+settings:
+ name "Console Mouse"
+ capability all=
+ nice 15
+
+script:
+ start {
+ # This works if gpm service is run as root, but if not then this should be in a separate rule file with appropriate access to write to /var/run (don't forget to chown!).
+ if [[ ! -d /var/run/mouse/ && -d /var/run ]] ; then
+ mkdir /var/run/mouse/
+ fi
+ }
+
+service:
+ pid_file /var/run/mouse/mouse.pid
+
+ # @todo consider a new type, such as "variable" than can be used to get the variable and store it in an iki parseable variable.
+ # This, however, may be too complicated than desirable (in terms of passing output back to the parent process).
+ # such as:
+ #variable device command fss_basic_read -can 0 device /etc/mouse
+ #variable protocal script {
+ # fss_basic_read -can 0 device /etc/mouse
+ #}
+ #variable options set ""
+
+ # @todo
+ start gpm -m variable:"device" -t variable:"protocol" variable:"options"
--- /dev/null
+# fss-000d
+#
+# Rule for setting the clock.
+#
+
+settings:
+ name "Setup Clock"
+ capability cap_sys_time=
+ nice 15
+
+ on start want boot filesystem
+ on start want net all
+
+script:
+ start {
+ clock_file=/etc/clock
+ clock_mode=
+ clock_server=
+ clock_ntpdate=
+
+ if [[ -f $clock_file ]] ; then
+ clock_mode=$(fss_basic_read -can 0 mode $clock_file);
+ clock_server=$(fss_basic_read -can 0 server $clock_file)
+ clock_ntpdate=$(fss_basic_read -can 0 ntpdate $clock_file)
+ fi
+
+ if [[ $clock_mode == "local" ]] ; then
+ hwclock --hctosys;
+ elif [[ $clock_mode == "ntp" ]] ; then
+ if [[ $clock_ntpdate == "yes" ]] ; then
+ ntpdate $clock_server &&
+ hwclock --systohc --utc
+ fi
+ elif [[ $clock_mode == "ntpdate" && $clock_host != "" ]] ; then
+ ntpdate $clock_server
+ elif [[ $clock_mode == "utc" ]] ; then
+ hwclock --hctosys --utc;
+ fi
+ }
--- /dev/null
+# fss-000d
+#
+# Rule for setting the keyboard.
+#
+
+settings:
+ name "System Keyboard"
+ nice 15
--- /dev/null
+# fss-000d
+#
+# Rule for executing ntpdate.
+#
+
+settings:
+ name "System Clock Using NTP Date"
+ capability cap_sys_time=
+ nice 15
+
+ on start want boot filesystem
+ on start need net all
+
+script:
+ start {
+ clock_file=/etc/clock
+ clock_mode=
+ clock_server=
+
+ if [[ -f $clock_file ]] ; then
+ clock_mode=$(fss_basic_read -can 0 mode $clock_file);
+ clock_server=$(fss_basic_read -can 0 server $clock_file)
+ fi
+
+ if [[ $clock_mode == "ntpdate" && $clock_host != "" ]] ; then
+ ntpdate $clock_server
+ fi
+ }
--- /dev/null
+# fss-000d
+#
+# Rule for the terminal programs.
+#
+# -m = don't prompt for login.
+# -J = don't clear on start, good for debugging.
+# 9600 and 115200 are common frequencies.
+
+settings:
+ name "System Terminal 4"
+
+command:
+ start agetty -8 tty4 linux
+
+ rerun start success delay 1000 reset
+ rerun start failure delay 5000 max 100
--- /dev/null
+# fss-000d
+#
+# Rule for the terminal programs.
+#
+# -m = don't prompt for login.
+# -J = don't clear on start, good for debugging.
+# 9600 and 115200 are common frequencies.
+
+settings:
+ name "System Terminal 1"
+
+command:
+ start agetty -8 -i -J - linux
+
+ rerun start success delay 1000 reset
+ rerun start failure delay 5000
--- /dev/null
+# fss-000d
+#
+# Rule for the terminal programs.
+#
+# -m = don't prompt for login.
+# -J = don't clear on start, good for debugging.
+# 9600 and 115200 are common frequencies.
+
+settings:
+ name "System Terminal 3"
+
+command:
+ start agetty -8 tty3 linux
+
+ rerun start success delay 1000 reset
+ rerun start failure delay 5000 max 100
--- /dev/null
+# fss-000d
+#
+# Rule for the terminal programs.
+#
+# -m = don't prompt for login.
+# -J = don't clear on start, good for debugging.
+# 9600 and 115200 are common frequencies.
+
+settings:
+ name "System Terminal 2"
+
+command:
+ start agetty -8 tty2 linux
+
+ rerun start success delay 1000 reset
+ rerun start failure delay 5000 max 100
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named actions.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named entry.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named exit.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named packet.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named rule.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named simulate.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0-or-later
+# license: cc-by-sa-4.0
# version 2024/07/02
#
# This file (assumed to be named time.txt) can be more easily read using the following iki_read commands:
/**
* Thread related defines.
+ *
+ * controller_thread_cleanup_interval_*_d:
+ * - long: How many seconds to wait for clean up for long waits.
+ * - short: How many seconds to wait for clean up for short waits.
+ *
+ * controller_thread_exit_*_d:
+ * - disable_force_times: The number of times to retry apply lock aon exit before forcibly setting state to disabled on exit.
+ * - process_cancel_total: The number of nanoseconds to wait when cancelling a process.
+ * - process_cancel_wait: The total number of times to wait when cancelling a process (multiply this by wait time to get total nanoseconds).
*/
#ifndef _di_controller_thread_d_
- #define controller_thread_cleanup_interval_long_d 3600 // 1 hour in seconds.
- #define controller_thread_cleanup_interval_short_d 180 // 3 minutes in seconds.
- #define controller_thread_exit_timeout_d 500 // 0.5 seconds in milliseconds.
+ #define controller_thread_cleanup_interval_long_d 3600 // 1 hour in seconds.
+ #define controller_thread_cleanup_interval_short_d 180 // 3 minutes in seconds.
+
+ #define controller_thread_exit_disable_force_times 12
#define controller_thread_exit_process_cancel_wait_d 600000000 // 0.6 seconds in nanoseconds.
#define controller_thread_exit_process_cancel_total_d 150 // 90 seconds in multiples of wait.
- #define controller_thread_simulation_timeout_d 200 // 0.2 seconds in milliseconds.
-
- #define controller_thread_signal_wait_timeout_seconds_d 70
- #define controller_thread_signal_wait_timeout_nanoseconds_d 0
-
- #define controller_thread_lock_read_timeout_seconds_d 3
- #define controller_thread_lock_read_timeout_nanoseconds_d 0
- #define controller_thread_lock_write_timeout_seconds_d 3
- #define controller_thread_lock_write_timeout_nanoseconds_d 0
-
- #define controller_thread_wait_timeout_1_before_d 4
- #define controller_thread_wait_timeout_2_before_d 12
- #define controller_thread_wait_timeout_3_before_d 28
-
- #define controller_thread_wait_timeout_1_seconds_d 0
- #define controller_thread_wait_timeout_1_nanoseconds_d 20000000 // 0.02 seconds in nanoseconds.
- #define controller_thread_wait_timeout_2_seconds_d 0
- #define controller_thread_wait_timeout_2_nanoseconds_d 200000000 // 0.2 seconds in nanoseconds.
- #define controller_thread_wait_timeout_3_seconds_d 2
- #define controller_thread_wait_timeout_3_nanoseconds_d 0
- #define controller_thread_wait_timeout_4_seconds_d 20
- #define controller_thread_wait_timeout_4_nanoseconds_d 0
-
- #define controller_thread_exit_helper_timeout_seconds_d 0
- #define controller_thread_exit_helper_timeout_nanoseconds_d 100000000 // 0.1 seconds in nanoseconds.
-
- #define controller_thread_exit_ready_timeout_seconds_d 0
- #define controller_thread_exit_ready_timeout_nanoseconds_d 500000000 // 0.5 seconds in nanoseconds.
#endif // _di_controller_thread_d_
+/**
+ * Thread related timeout defines.
+ *
+ * controller_thread_timeout_*_d:
+ * - exit: The number of milliseconds to wait before exit times out (before a terminate/kill signal is sent).
+ * - exit_disable_force_nanoseconds: The nanoseconds to wait between each attempt to lock and set disable state.
+ * - exit_disable_force_seconds: The seconds to wait between each attempt to lock and set disable state.
+ * - exit_helper_nanoseconds: The nanoseconds to wait before the exit helper times out.
+ * - exit_helper_seconds: The seconds to wait before the exit helper times out.
+ * - exit_ready_nanoseconds: The nanoseconds to wait before the exit ready times out.
+ * - exit_ready_seconds: The seconds to wait before the exit ready times out.
+ * - lock_read_nanoseconds: The nanoseconds to wait before the read lock times out.
+ * - lock_read_seconds: The seconds to wait before the read lock times out.
+ * - lock_write_nanoseconds: The nanoseconds to wait before the write lock times out.
+ * - lock_write_seconds: The seconds to wait before the write lock times out.
+ * - simulation: The number of milliseconds to wait to simulate a pause due to a process execution.
+ * - wait_signal_nanoseconds: The nanoseconds to wait before waiting for the signal times out.
+ * - wait_signal_seconds: The seconds to wait before waiting for the signal times out.
+ * - wait_1_before: The max number of retries to perform set 1 wait timeouts.
+ * - wait_1_nanoseconds: The nanoseconds to wait in set 1 timeouts while waiting for an Instance.
+ * - wait_1_seconds: The seconds to wait in set 1 timeouts while waiting for an Instance.
+ * - wait_2_before: The max number of retries to perform set 2 wait timeouts (after set 1 wait before is exceeded).
+ * - wait_2_nanoseconds: The nanoseconds to wait in set 2 timeouts while waiting for an Instance.
+ * - wait_2_seconds: The seconds to wait in set 2 timeouts while waiting for an Instance.
+ * - wait_3_before: The max number of retries to perform set 3 wait timeouts (after set 2 wait before is exceeded).
+ * - wait_3_nanoseconds: The nanoseconds to wait in set 3 timeouts while waiting for an Instance.
+ * - wait_3_seconds: The seconds to wait in set 3 timeouts while waiting for an Instance.
+ * - wait_4_nanoseconds: The nanoseconds to wait in set 4 timeouts while waiting for an Instance.
+ * - wait_4_seconds: The seconds to wait in set 4 timeouts while waiting for an Instance.
+ */
+#ifndef _di_controller_thread_timeout_d_
+ #define controller_thread_timeout_exit_d 500 // 0.5 seconds in milliseconds.
+ #define controller_thread_timeout_exit_disable_force_nanoseconds_d 10000000 // 0.01 seconds in nanoseconds.
+ #define controller_thread_timeout_exit_disable_force_seconds_d 0
+ #define controller_thread_timeout_exit_helper_nanoseconds_d 100000000 // 0.1 seconds in nanoseconds.
+ #define controller_thread_timeout_exit_helper_seconds_d 0
+ #define controller_thread_timeout_exit_ready_nanoseconds_d 500000000 // 0.5 seconds in nanoseconds.
+ #define controller_thread_timeout_exit_ready_seconds_d 0
+
+ #define controller_thread_timeout_lock_read_nanoseconds_d 0
+ #define controller_thread_timeout_lock_read_seconds_d 3
+ #define controller_thread_timeout_lock_write_nanoseconds_d 0
+ #define controller_thread_timeout_lock_write_seconds_d 3
+
+ #define controller_thread_timeout_simulation_d 200 // 0.2 seconds in milliseconds.
+
+ #define controller_thread_timeout_wait_1_before_d 4
+ #define controller_thread_timeout_wait_1_nanoseconds_d 20000000 // 0.02 seconds in nanoseconds.
+ #define controller_thread_timeout_wait_1_seconds_d 0
+ #define controller_thread_timeout_wait_2_before_d 12
+ #define controller_thread_timeout_wait_2_nanoseconds_d 200000000 // 0.2 seconds in nanoseconds.
+ #define controller_thread_timeout_wait_2_seconds_d 0
+ #define controller_thread_timeout_wait_3_before_d 28
+ #define controller_thread_timeout_wait_3_nanoseconds_d 0
+ #define controller_thread_timeout_wait_3_seconds_d 2
+ #define controller_thread_timeout_wait_4_nanoseconds_d 0
+ #define controller_thread_timeout_wait_4_seconds_d 20
+ #define controller_thread_timeout_wait_signal_nanoseconds_d 0
+ #define controller_thread_timeout_wait_signal_seconds_d 70
+#endif // _di_controller_thread_timeout_d_
+
#ifdef __cplusplus
} // extern "C"
#endif
0, \
0, \
0, \
- controller_thread_exit_timeout_d, \
+ controller_thread_timeout_exit_d, \
0, \
0, \
0, \
0, \
0, \
flag, \
- controller_thread_exit_timeout_d, \
+ controller_thread_timeout_exit_d, \
0, \
0, \
0, \
do {
f_thread_mutex_lock(&instance->wait_lock);
- if (count < controller_thread_wait_timeout_1_before_d) {
- controller_time_now(controller_thread_wait_timeout_1_seconds_d, controller_thread_wait_timeout_1_nanoseconds_d, &time);
+ if (count < controller_thread_timeout_wait_1_before_d) {
+ controller_time_now(controller_thread_timeout_wait_1_seconds_d, controller_thread_timeout_wait_1_nanoseconds_d, &time);
}
- else if (count < controller_thread_wait_timeout_2_before_d) {
- controller_time_now(controller_thread_wait_timeout_2_seconds_d, controller_thread_wait_timeout_2_nanoseconds_d, &time);
+ else if (count < controller_thread_timeout_wait_2_before_d) {
+ controller_time_now(controller_thread_timeout_wait_2_seconds_d, controller_thread_timeout_wait_2_nanoseconds_d, &time);
}
- else if (count < controller_thread_wait_timeout_3_before_d) {
- controller_time_now(controller_thread_wait_timeout_3_seconds_d, controller_thread_wait_timeout_3_nanoseconds_d, &time);
+ else if (count < controller_thread_timeout_wait_3_before_d) {
+ controller_time_now(controller_thread_timeout_wait_3_seconds_d, controller_thread_timeout_wait_3_nanoseconds_d, &time);
}
else {
- controller_time_now(controller_thread_wait_timeout_4_seconds_d, controller_thread_wait_timeout_4_nanoseconds_d, &time);
+ controller_time_now(controller_thread_timeout_wait_4_seconds_d, controller_thread_timeout_wait_4_nanoseconds_d, &time);
}
status = f_thread_condition_wait_timed(&time, &instance->wait, &instance->wait_lock);
if (status != F_time) {
// move up the wait timer after a trigger was received.
- if (count < controller_thread_wait_timeout_2_before_d) {
+ if (count < controller_thread_timeout_wait_2_before_d) {
count = 0;
}
- else if (count < controller_thread_wait_timeout_3_before_d) {
- count = controller_thread_wait_timeout_1_before_d;
+ else if (count < controller_thread_timeout_wait_3_before_d) {
+ count = controller_thread_timeout_wait_1_before_d;
}
else {
- count = controller_thread_wait_timeout_2_before_d;
+ count = controller_thread_timeout_wait_2_before_d;
}
}
f_thread_unlock(&instance->lock);
- if (count < controller_thread_wait_timeout_3_before_d) {
+ if (count < controller_thread_timeout_wait_3_before_d) {
++count;
}
memset(&time, 0, sizeof(f_time_spec_t));
- controller_time_now(controller_thread_lock_read_timeout_seconds_d, controller_thread_lock_read_timeout_nanoseconds_d, &time);
+ controller_time_now(controller_thread_timeout_lock_read_seconds_d, controller_thread_timeout_lock_read_nanoseconds_d, &time);
status = f_thread_lock_read_timed(&time, lock);
for (f_time_spec_t time; ; ) {
- controller_time_now(controller_thread_lock_write_timeout_seconds_d, controller_thread_lock_write_timeout_nanoseconds_d, &time);
+ controller_time_now(controller_thread_timeout_lock_write_seconds_d, controller_thread_timeout_lock_write_nanoseconds_d, &time);
status = f_thread_lock_write_timed(&time, lock);
{
f_time_spec_t delay = f_time_spec_t_initialize;
- status = f_time_spec_millisecond(0, controller_thread_simulation_timeout_d, &delay);
+ status = f_time_spec_millisecond(0, controller_thread_timeout_simulation_d, &delay);
if (F_status_is_error(status)) {
controller_print_error_status(&main->program.error, macro_controller_f(f_time_spec_millisecond), F_status_set_fine(status));
{
f_time_spec_t delay = f_time_spec_t_initialize;
- status = f_time_spec_millisecond(0, controller_thread_simulation_timeout_d, &delay);
+ status = f_time_spec_millisecond(0, controller_thread_timeout_simulation_d, &delay);
if (F_status_is_error(status)) {
controller_print_error_status(&main->program.error, macro_controller_f(f_time_spec_millisecond), F_status_set_fine(status));
if (F_status_is_error_not(*status) && *status != F_child && main->program.parameters.array[controller_parameter_validate_e].result == f_console_result_none_e && main->process.mode == controller_process_mode_helper_e) {
f_time_spec_t time;
- time.tv_sec = controller_thread_exit_helper_timeout_seconds_d;
- time.tv_nsec = controller_thread_exit_helper_timeout_nanoseconds_d;
+ time.tv_sec = controller_thread_timeout_exit_helper_seconds_d;
+ time.tv_nsec = controller_thread_timeout_exit_helper_nanoseconds_d;
nanosleep(&time, 0);
return 0;
}
- if (F_status_is_error_not(f_thread_mutex_lock(&main->thread.lock.alert))) {
- main->thread.enabled = controller_thread_enabled_not_e;
-
- f_thread_mutex_unlock(&main->thread.lock.alert);
- }
+ controller_thread_instance_force_set_disable(main);
f_thread_condition_signal_all(&main->thread.lock.alert_condition);
const f_status_t status = controller_rule_instance_perform(controller_instance_option_asynchronous_e, instance);
- // A forked child instance should de-allocate memory on exit.
- // It seems that this function doesn't return to the calling thread for a forked child instance, even with the "return 0;" below.
+ // A forked child Instance should de-allocate memory on exit.
+ // It seems that this function doesn't return to the calling thread for a forked child Instance, even with the "return 0;" below.
if (status == F_child) {
controller_delete(instance->main);
instance = main->thread.instances.array[i];
- // Do not cancel Exit instances, when not performing "execute" during exit.
+ // Do not cancel Exit Instances, when not performing "execute" during exit.
if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) {
continue;
}
instance = main->thread.instances.array[i];
- // Do not wait for instances, when not performing "execute" during exit.
+ // Do not wait for Instances, when not performing "execute" during exit.
if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) {
continue;
}
while (instance->childs.array[j] > 0 && lapsed < entry->timeout_exit) {
- // A hackish way to determine if the child instance exists while waiting (@todo look into pidfd() and epoll_wait()).
+ // A hackish way to determine if the child Instance exists while waiting (@todo look into pidfd() and epoll_wait()).
if (getpgid(instance->childs.array[j]) >= 0) {
time.tv_sec = 0;
time.tv_nsec = interval_nanoseconds;
if (pid) {
while (lapsed < entry->timeout_exit) {
- // A hackish way to determine if the instance exists while waiting (@todo look into pidfd() and epoll_wait()).
+ // A hackish way to determine if the Instance exists while waiting (@todo look into pidfd() and epoll_wait()).
if (getpgid(pid) >= 0) {
time.tv_sec = 0;
time.tv_nsec = interval_nanoseconds;
instance = main->thread.instances.array[i];
- // Do not kill Exit instances, when not performing "execute" during exit.
+ // Do not kill Exit Instances, when not performing "execute" during exit.
if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) continue;
if (instance->id_thread) {
// Shrink the child pids as much as possible.
while (instance->childs.used) {
- // Do not shrink below an Exit instances, when not performing "execute" during exit.
+ // Do not shrink below an Exit Instances, when not performing "execute" during exit.
if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) break;
if (instance->childs.array[j] > 0) break;
// Shrink the path pids as much as possible.
while (instance->path_pids.used) {
- // Do not shrink below an Exit instances, when not performing "execute" during exit.
+ // Do not shrink below an Exit Instances, when not performing "execute" during exit.
if (instance->type == controller_instance_type_exit_e && main->thread.enabled != controller_thread_enabled_exit_execute_e) break;
if (instance->path_pids.array[j].used) break;
controller_print_error_status(&main->program.error, macro_controller_f(f_thread_create), F_status_set_fine(status));
}
- if (F_status_is_error_not(f_thread_mutex_lock(&main->thread.lock.alert))) {
- main->thread.enabled = controller_thread_enabled_not_e;
-
- f_thread_mutex_unlock(&main->thread.lock.alert);
- }
+ controller_thread_instance_force_set_disable(main);
}
else {
f_time_spec_t time = f_time_spec_t_initialize;
status = f_thread_mutex_lock(&main->thread.lock.alert);
if (F_status_is_error(status)) break;
- controller_time_now(controller_thread_exit_ready_timeout_seconds_d, controller_thread_exit_ready_timeout_nanoseconds_d, &time);
+ controller_time_now(controller_thread_timeout_exit_ready_seconds_d, controller_thread_timeout_exit_ready_nanoseconds_d, &time);
status = f_thread_condition_wait_timed(&time, &main->thread.lock.alert_condition, &main->thread.lock.alert);
} while (F_status_is_error_not(status) && main->thread.enabled == controller_thread_enabled_exit_e);
- if (F_status_is_error(status)) {
- if (F_status_is_error_not(f_thread_mutex_lock(&main->thread.lock.alert))) {
- main->thread.enabled = controller_thread_enabled_not_e;
-
- f_thread_mutex_unlock(&main->thread.lock.alert);
- }
- }
+ if (F_status_is_error(status)) controller_thread_instance_force_set_disable(main);
}
// The sigtimedwait() function that is run inside of signal must be interrupted via the f_thread_cancel().
controller_thread_instance_cancel(main, F_false, controller_thread_cancel_exit_e);
}
else {
- if (F_status_is_error_not(f_thread_mutex_lock(&main->thread.lock.alert))) {
+ controller_thread_instance_force_set_disable(main);
+ }
+ }
+#endif // _di_controller_thread_instance_exit_
+
+#ifndef _di_controller_thread_instance_force_set_disable_
+ void controller_thread_instance_force_set_disable(controller_t * const main) {
+
+ if (!main) return;
+
+ if (F_status_is_error_not(f_thread_mutex_lock(&main->thread.lock.alert))) {
+ main->thread.enabled = controller_thread_enabled_not_e;
+
+ f_thread_mutex_unlock(&main->thread.lock.alert);
+
+ return;
+ }
+
+ f_time_spec_t time;
+
+ for (uint8_t i = 0; i < controller_thread_exit_disable_force_times; ++i) {
+
+ memset((void *) &time, 0, sizeof(struct timespec));
+
+ controller_time_now(controller_thread_timeout_exit_disable_force_seconds_d, controller_thread_timeout_exit_disable_force_nanoseconds_d, &time);
+
+ if (F_status_is_error_not(f_thread_mutex_lock_timed(&time, &main->thread.lock.alert))) {
main->thread.enabled = controller_thread_enabled_not_e;
f_thread_mutex_unlock(&main->thread.lock.alert);
+
+ return;
}
- }
+ } // for
+
+ // Forcibly set disable regardless of the risk.
+ main->thread.enabled = controller_thread_enabled_not_e;
}
-#endif // _di_controller_thread_instance_exit_
+#endif // _di_controller_thread_instance_force_set_disable_
#ifndef _di_controller_thread_instance_normal_
void * controller_thread_instance_normal(void * const argument) {
#endif // _di_controller_thread_instance_exit_
/**
+ * Set the execution state to disabled during exiting and force the case if need be.
+ *
+ * The program must exit during the Exit process.
+ * The state must be properly set.
+ * Perform a limited number of attempts to set the state to exiting.
+ * Should this fail, then force the case regardless of the risk.
+ *
+ * @param main
+ * The main program data.
+ *
+ * Must not be NULL.
+ *
+ * This does not alter main.setting.state.status.
+ *
+ * The main.thread.lock.alert lock will be set and then unset if possible.
+ * The main.thread.enabled will be updated and set to controller_thread_enabled_not_e.
+ */
+#ifndef _di_controller_thread_instance_force_set_disable_
+ extern void controller_thread_instance_force_set_disable(controller_t * const main);
+#endif // _di_controller_thread_instance_force_set_disable_
+
+/**
* Asynchronously execute a Rule process during normal operations.
*
* @param argument
memset((void *) &information, 0, sizeof(siginfo_t));
- controller_time_now(controller_thread_exit_ready_timeout_seconds_d, controller_thread_exit_ready_timeout_nanoseconds_d, &time);
+ controller_time_now(controller_thread_timeout_exit_ready_seconds_d, controller_thread_timeout_exit_ready_nanoseconds_d, &time);
if (f_signal_wait_until(&main->program.signal.set, &time, &information) == F_time_out) continue;
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named entry.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named exit.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named packet.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named rule.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
+# license: open-standard-license-1.0-or-later
# version 2024/07/02
#
# This file (assumed to be named task.txt) can be more easily read using the following iki_read commands:
# fss-0002 iki-0000
#
-# license: open-standard-license-1.0
-# version 2023/12/16
+# license: open-standard-license-1.0-or-later
+# version 2024/07/02
#
# This file (assumed to be named time.txt) can be more easily read using the following iki_read commands:
# iki_read time.txt +Q -r UTC UTC -w -WW character "'" "'" code '"' '"'