blob: d5cf0bb11c663f15f07a9d483dfd4a2148ba0185 [file] [log] [blame]
2009-10-03 Scott James Remnant <scott@netsplit.com>
* init/Makefile.am ($(com_ubuntu_Upstart_OUTPUTS)):
($(com_ubuntu_Upstart_Job_OUTPUTS)):
($(com_ubuntu_Upstart_Instance_OUTPUTS)):
* util/Makefile.am ($(com_ubuntu_Upstart_OUTPUTS)):
($(com_ubuntu_Upstart_Job_OUTPUTS)):
($(com_ubuntu_Upstart_Instance_OUTPUTS)): Use pre-built nih-dbus-tool
when necessary (e.g. cross-compiling)
* util/shutdown.c (shutdown_now): Free error before exiting.
* conf/rc-sysinit.conf: Improve regular expression so that it
doesn't match commented-out inittab lines.
2009-08-04 Johan Kiviniemi <johan@kiviniemi.name>
* conf/rc-sysinit.conf: Don't replace DEFAULT_RUNLEVEL with an
empty string when there is no "initdefault" line in /etc/inittab
2009-08-02 Scott James Remnant <scott@netsplit.com>
* NEWS: Release 0.6.3
2009-08-01 Scott James Remnant <scott@netsplit.com>
* init/tests/test_job_process.c (test_handler): Add a missing test
case for the running process exiting while we're in the stopping
state.
* init/job_process.c (job_process_terminated): Don't change the
state or record failure information if we're in the stopping state
when the main process dies, otherwise we hit an assertion later;
just wait for the stopping event to finish and carry on as before.
2009-07-31 Scott James Remnant <scott@netsplit.com>
* dbus/upstart.h: Allow the service name and address to be overriden
2009-07-29 Michael Biebl <mbiebl@gmail.com>
* init/tests/test_job_process.c: Add missing sys/ptrace.h include
2009-07-21 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.6.3
* NEWS: Begin new release
* NEWS: Release 0.6.2
* init/main.c (crash_handler): Restore missing chdir ("/") call.
* init/tests/test_job_process.c (test_handler): We should allow
a job to exec() before it calls fork() to allow shell scripts to
exec daemons.
* init/job_process.c (job_process_trace_exec): Continue the traced
process instead of detaching if it has not yet forked.
* init/job.c (job_change_state): Obvious bug fix; the set of states
into which we can enter JOB_STOPPING includes JOB_STARTING because
we can get the "stop" event or command there.
2009-07-16 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.6.2
* NEWS: Begin new release
* NEWS: Release 0.6.1
* util/runlevel.c: Output the path before the error message,
to make it clear that it's the utmp file missing not runlevel.
* util/runlevel.c: If there is no current runlevel because the
environment variable is empty, output "unknown" instead of "N N".
2009-07-15 Scott James Remnant <scott@netsplit.com>
* README: Now that D-Bus 1.2.16 proper has been released, update
our requirements.
2009-07-14 Scott James Remnant <scott@netsplit.com>
* TODO: Update
* init/tests/test_job_process.c (test_handler): Rework the existing
ptrace fork handler test case to make sure we test the case where
we get the fork event before the stopped child. Add a second test
case for the opposite (stopped child before the fork event) which
we don't currently handle.
* init/job_process.c (job_process_trace_fork): Test for the missed
child event using ptrace(), if it succeeds the child is ready so
we can just assume we had the event.
* util/Makefile.am (EXTRA_DIST): Distribute the valgrind suppressions
file
* util/tests/test_utmp.c (test_write_shutdown): Additional instance
of the same test.
* util/tests/test_utmp.c (test_write_runlevel): Looks like glibc
is fixed to return the right error code.
2009-07-11 Scott James Remnant <scott@netsplit.com>
* init/control.c (control_server_open): Don't hardcode the server
address, otherwise the test suite can't test this function.
* init/tests/test_control.c (test_server_open)
(test_server_connect, test_server_close): Change the server
address in the tests.
* configure.ac: Bump version to 0.6.1
* NEWS: Begin new release
2009-07-09 Scott James Remnant <scott@netsplit.com>
* NEWS: Release 0.6.0
* README: Note that we need D-Bus GIT HEAD.
* NEWS: Update.
* init/man/inittab.5: People keep trying "man inittab", so explain
that it's gone.
* init/Makefile.am (dist_man_MANS): Install it
* NEWS: Declare the "lacks documentation" bug fixed
* init/man/init.8: Refresh and turn it into more of an overview
of Upstart now that we have lots of other pages to refer to.
* init/man/upstart.7: Since it's an overview, people might go
"man upstart" so redirect to it.
* init/man/init.5: Actually document the configuration format.
* init/Makefile.am (dist_man_MANS): Install the configuration
documentation, and the redirect.
* util/man/runlevel.8, util/man/telinit.8, util/man/shutdown.8,
* util/man/reboot.8: Add environment and files sections.
* init/man/startup.7, init/man/starting.7, init/man/started.7,
* init/man/stopping.7, init/man/stopped.7
* init/man/control-alt-delete.7, init/man/keyboard-request.7,
* init/man/power-status-changed.7: Write manual pages for each
of the events generated by the init daemon by default.
* init/Makefile.am (dist_man_MANS): Distribute and install the
new manpages.
* util/man/runlevel.7: Indent the example, don't boldface
* init/job.c (job_start, job_stop, job_restart): Restructure
slightly to avoid gcc warning
* init/job_class.c (job_class_start, job_class_restart): Make the
same change to these too
* util/shutdown.c: Warn if we can't change directory
* util/telinit.c: Assert that we don't fall out of the switch
* init/tests/test_job_class.c (test_get_version)
(test_get_author, test_get_description, test_get_name): Initialise
alloc-safe variables to NULL to avoid gcc warning
* util/tests/test_initctl.c (test_job_status, test_start_action)
(test_stop_action, test_restart_action, test_status_action)
(test_list_action, test_emit_action)
(test_reload_configuration_action, test_version_action)
(test_log_priority_action, test_upstart_open): Initialise alloc-safe
variables to NULL and diverted return values to 0 to avoid gcc
warnings.
(test_start_action, test_stop_action, test_restart_action):
Replace sigsetjmp/siglongjmp with a call to _exit() in the handler
* util/tests/test_sysv.c (test_change_runlevel): Initialise alloc-safe
variables to NULL to avoid gcc warnings
* util/man/runlevel.7: Formatting fixes, and mention that rcS
runs rc-sysinit again.
* util/man/runlevel.8: s/utilities/tools/
* util/man/telinit.8: s/utilities/tools/
* util/man/shutdown.8: s/utilities/tools/
* util/man/reboot.8: s/utilities/programs/
* util/man/initctl.8: s/utility/tool/
* init/job_class.h (JobClass): Drop the leader option; at the time
it seemed to make sense that Upstart would provide a "daemon"-like
environment, but it really doesn't in practice. Software should
feel safe to daemonise on its own, and I'd rather fix supervision
of those; freeing up Upstart jobs to run as new sessions by default
again. This is also the only real option that would change the
behaviour between 0.6 and 0.10 in an awkwardly compatible way.
* init/job_class.c (job_class_new): Remove leader initialisation
* init/tests/test_job_class.c (test_new): Drop the initialisation
check for leader
* init/parse_job.c (stanza_session): Drop the stanza
* init/tests/test_parse_job.c (test_stanza_session): Drop the
stanza test cases.
* init/job_process.c (job_process_spawn): Drop the double-fork.
This means we don't need to read the pid of our extra child either.
(job_process_error_read): we no longer need a fork error.
* init/job_process.h (JobProcessErrorType): Drop the fork error.
* init/tests/test_job_process.c (test_spawn): Replace the simple job
test case with the session leader test case, now that's the default.
(test_run, test_spawn, test_kill, test_handler): Remove all the
class->leader = TRUE from the tests, we only ever really tested
session leaders anyway since that's all the test suite could follow
* init/tests/test_job.c (test_change_goal, test_change_state):
Remove the leader flag from test jobs
* init/tests/test_event.c (test_pending, test_finished): Remove
the leader flag from test jobs.
* init/job_process.c (job_process_catch_runaway): Use a monotonic
clock, not the realtime clock, for respawn interval detection.
* init/tests/test_job_process.c (test_kill, test_handler): Use the
monotonic clock in test cases too
* init/Makefile.am (init_LDADD): Link with librt
* NEWS: Update.
* util/utmp.c (utmp_write_runlevel): Don't write 'N' to utmp or
wtmp for the previous runlevel, this will force writing reboot
records if prevlevel='N'/0 since read_runlevel will always return
'N' in that case.
* util/tests/test_utmp.c (test_write_runlevel): Add test case for
passing 'N' and having it treated as zero
(test_read_runlevel): Add a couple of test cases for the problems
we found last night where shutdown and corrupt utmp records result
in the wrong data being returned.
* util/tests/test_sysv.c (test_change_runlevel): Add a test case
for switching from sysinit to the first runlevel
* init/conf.h,
* init/control.h,
* init/event.h,
* init/job_class.h: Variable declarations in header files need to
be prefixed with "extern", the NIH_BEGIN_EXTERN stuff only applies
to C++.
* util/reboot.c: Reboot can't write the shutdown time before
calling shutdown, otherwise shutdown won't be able to get the
current runlevel anymore.
* util/man/reboot.8: Update, we don't write the shutdown time
before calling shutdown - it's up to the shutdown scripts to
call reboot -w before remounting the root filesystem.
* util/tests/test_utmp.c (test_get_runlevel): Replace test case
with one that expects 'N' rather than fall-through.
* util/tests/test_sysv.c (test_change_runlevel): Expect N when
there is no previous runlevel
* util/utmp.c (utmp_read_runlevel): Also catch a zero runlevel from
utmp, replacing with 'N' - these functions should never return 0
* util/sysv.c (sysv_change_runlevel): Should set prevlevel to N
when we don't find one
* util/utmp.c (utmp_read_runlevel): Catch a negative runlevel from
corrupt utmp data, convert to 'N'
(utmp_get_runlevel): Return N when RUNLEVEL is set but empty,
rather than falling through
* util/telinit.c: Catch a missing argument separately so we don't
output "(null)"
* README: Update requirements.
* TODO: Update.
* conf/rc-sysinit.conf: Fix typo.
2009-07-08 Scott James Remnant <scott@netsplit.com>
* conf/rc-sysinit.conf: Michael Biebl pointed out that by setting
the runlevel to "S" during sysinit, we end up with the runlevel
after boot being "S 2" - and that means scripts in rc2.d that
are also in rcS.d won't get started. The way we had it before
("N 2") was correct. This happily fixes the one corner case our
reboot handling didn't cover - crashing in single user mode and
rebooting.
* util/telinit.c: Fix missing ret = from kill
* conf/rc-sysinit.conf: Ignore -s/single if we're already coming
from single-user-mode.
* util/telinit.c (options): Unignore the -t option
* NEWS: Update.
* init/main.c (hup_handler): Also try and reconnect to the message
bus if we've lost the connection.
* init/conf.c (conf_source_reload_dir): Don't blacklist certain
patterns from the configuration directory, instead just filter
to whitelist.
(conf_dir_filter): Whitelist filter, only accept files ending
in .conf
(conf_reload_path): Strip .conf from the filename to generate
the job name.
(conf_file_filter): Add the extra is_dir argument.
* init/tests/test_conf.c (test_source_reload_job_dir)
(test_source_reload_conf_dir, test_source_reload_file)
(test_source_reload): Append .conf to all our filenames
* init/tests/test_control.c (test_reload_configuration): Append
.conf to filenames here too
* NEWS: Update.
* init/job_process.c (job_process_run): Stop being stingy, the
post-stop script can have the stop environment too
* init/tests/test_job_process.c (test_run): Add a test case to
make sure it is.
2009-07-08 Michael Biebl <mbiebl@gmail.com>
* contrib/vim/syntax/upstart.vim: Upstart job syntax highlighting
* contrib/vim/ftdetect/upstart.vim: Use for the /etc/init directory
* contrib/Makefile.am: Include the vim syntax files in the
distribution
* configure.ac (AC_CONFIG_FILES): Create contrib/Makefile
* Makefile.am (SUBDIRS): Recurse into the contrib sub-directory
2009-07-08 Scott James Remnant <scott@netsplit.com>
* conf/rc.conf: This doesn't need to be an instance job, Upstart
will do the right thing and stop the task before starting it again
with the new environment (I spent so much time on that, you'd think
I'd remember :p)
* conf/control-alt-delete.conf: Default job for Control-Alt-Delete
* conf/rc-sysinit.conf: Default job for system initialisation
* conf/rc.conf: A fully wacky instance job that runs the rc script
for runlevel changes
* conf/rcS.conf: And a job for single-user-mode, which calls back
to rc-sysinit
* conf/Makefile.am (dist_init_DATA): Install the default files
into the /etc/init directory
* configure.ac (AC_CONFIG_FILES): Create conf/Makefile
* Makefile.am (SUBDIRS): Recurse into the conf directory.
* util/initctl.c (upstart_open, start_action, stop_action)
(restart_action, status_action, list_action): Don't auto-start
the init daemon, it makes no sense.
(upstart_open): When not running from the test suite, and not as
root, it makes sense to default to using the system bus daemon.
* util/tests/test_initctl.c (test_upstart_open): Make sure that
auto-start is FALSE, not TRUE.
* NEWS: Update.
* util/Makefile.am (dist_man_MANS): Oops, had the wrong name for
the runlevel(7) manpage.
* util/shutdown.c: Gets a bit of a redress, but not much of rewrite
since this is largely just compatibility madness.
(shutdown_now): Port to use sysv_change_runlevel()
(warning_message): Construct plural forms a little better.
(wall): use utmpx, rather than utmp
* util/man/shutdown.8: Minor tweaks and improvements
* NEWS: Update.
* util/reboot.c: Following the pattern of the previous, remove much
of the reboot code, but in the process adding support for reboot
implying --force in runlevel 0 or 6, and writing the shutdown
wtmp record.
* util/man/reboot.8: Minor updates.
* NEWS: Update.
* util/telinit.c: Drop quite a bit of the code of telinit too,
just becoming a wrapper about sysv_change_runlevel() - also support
Qq/Uu by using kill()
* util/tests/test_telinit.c (test_env_option): Since we have an
env option, we should test it.
* util/man/telinit.8: Update the manual page.
* util/man/runlevel.8: Typo (/var/run/wtmp -> /var/log/wtmp)
* util/Makefile.am (TESTS): Run the new test
(test_telinit_SOURCES, test_telinit_CFLAGS)
(test_telinit_LDFLAGS, test_telinit_LDADD): Details for the
test suite binary
* NEWS: Update.
* util/runlevel.c: Drop about 90% of the code, this just becomes
a wrapper around utmp_get_runlevel()
* util/man/runlevel.8: Update the runlevel manpage.
* util/man/runlevel.7: Also put together a manual page that
describes the runlevel event, as well as the implementation in
Upstart.
* util/Makefile.am (dist_man_MANS): Install the new manpage.
* NEWS: Update.
* util/Makefile.am (reboot_SOURCES, runlevel_SOURCES): Compile and
link the utmp handling source, depending on the header.
(reboot_LDADD, runlevel_LDADD): Drop dependency on libupstart
(shutdown_SOURCES, telinit_SOURCES): Compile and link both the
utmp handling and sysv compat source, depending on the headers
(nodist_shutdown_SOURCES, nodist_telinit_SOURCES): Also link in
the auto-generated bindings
(shutdown_LDADD, telinit_LDADD): Drop dependencies on libupstart,
replacing with dependencies on libnih-dbus and the D-Bus libs.
(runlevel_SOURCES, runlevel_LDFLAGS, runlevel_LDADD)
(shutdown_SOURCES, shutdown_LDFLAGS, shutdown_LDADD)
(telinit_SOURCES, telinit_LDFLAGS, telinit_LDADD): Remove duplicate
entries mistakenly copied from compat/sysv
* util/sysv.c (sysv_change_runlevel): Pretty much the core compat
function for System V, generate a runlevel event and store the
appropriate things in utmp and wtmp.
* util/sysv.h: Prototype.
* util/tests/test_sysv.c: Test cases for the new function.
* util/Makefile.am (TESTS): Run the sysv test cases
(test_sysv_SOURCES, nodist_test_sysv_SOURCES, test_sysv_LDFLAGS)
(test_sysv_LDADD): Details for the sysv test cases, which obviously
depend on the auto-generated bindings code.
* util/utmp.c (utmp_write_runlevel): Make sure that it's ok to
have no previous runlevel.
* util/tests/test_utmp.c (test_write_runlevel): Add no previous
runlevel test.
* util/utmp.c (utmp_read_runlevel): Don't call utmpxname() if we
don't pass a utmp_file, letting glibc pick the default.
* util/tests/test_utmp.c (test_read_runlevel): Add a test case for
no filename.
* util/util.supp: utmpname leaks memory, so suppress it from valgrind
* util/utmp.c: Set of functions for dealing with utmp and wtmp
(utmp_read_runlevel): Read the current runlevel from the file
(utmp_get_runlevel): Obtain the current runlevel from the
environment, or the file if not set
(utmp_write_runlevel): Write a runlevel change record, and also
deal with the reboot record if the utmp or wtmp files don't quite
match.
(utmp_write_shutdown): Write a shutdown time record
(utmp_entry, utmp_write, wtmp_write): utility functions for creating
and writing utmp and wtmp records.
* util/utmp.h: Prototypes for new functions.
* util/tests/test_utmp.c: Test cases.
* util/Makefile.am (test_utmp_SOURCES, test_utmp_LDFLAGS)
(test_utmp_LDADD): Details for utmp test cases
(tests): Move to the bottom of the file and make PHONY
2009-07-07 Scott James Remnant <scott@netsplit.com>
* util/man/initctl.8: Improve the manpage.
2009-07-06 Scott James Remnant <scott@netsplit.com>
* util/initctl.c: Rewrite from scratch, utilising the current
D-Bus API and auto-generated method functions for it.
* util/tests/test_initctl.c: Rewrite from scratch to test all
of the new methods.
* util/Makefile.am (test_initctl_CFLAGS): Include AM_CFLAGS
(install-data-hook, install-exec-hook): Install a symlink for
"restart" as well.
* NEWS: Update.
2009-07-03 Scott James Remnant <scott@netsplit.com>
* dbus/com.ubuntu.Upstart.Instance.xml (Start, Stop, Restart): add
wait arguments to the instance commands as well.
* init/job.c (job_start, job_stop, job_restart): Add wait arguments,
when TRUE the functions behave as before; when FALSE the methods
return after changing the goal and no blocked entries are created.
* init/job.h: Amend prototypes.
* init/tests/test_job.c (test_start, test_stop, test_restart):
Pass TRUE for wait and check for a blocking entry in existing tests,
add tests for passing FALSE and making sure that there's no blocking
but we still get the reply.
* dbus/com.ubuntu.Upstart.Job.xml (Start, Stop, Restart): Add wait
arguments to these too
* init/job_class.c (job_class_start, job_class_stop)
(job_class_restart): Add wait arguments, when TRUE the functions
behave as before; when FALSE the methods return after changing
the goal and no blocked entries are created.
* init/job_class.h: Amend prototypes.
* init/tests/test_job_class.c (test_start, test_stop, test_restart):
Pass TRUE for wait and check for a blocking entry in existing tests,
add tests for passing FALSE and making sure that there's no blocking
but we still get the reply.
(test_get_name, test_get_description, test_get_author)
(test_get_version): Add missing code to free the class on enomem
* dbus/com.ubuntu.Upstart.xml (EmitEvent): Add wait argument
* init/control.c (control_emit_event): Add wait argument, when TRUE
this behaves as before; when FALSE the method returns after queuing
the event and no blocked entry is created for it.
* init/control.h: Amend prototype.
* init/tests/test_control.c (test_emit_event): Pass TRUE for wait
and check for a blocking entry in existing tests, add a test for
passing FALSE and making sure that there's no blocking but we
still get the reply.
* dbus/com.ubuntu.Upstart.Instance.xml: Add a "processes" property
to obtain the list of current job processes, both their type and
their pid.
* init/job.c (job_get_processes): Implement the new property accessor
* init/job.h: Add prototype
* init/tests/test_job.c (test_get_processes): Add test cases for
returning process arrays.
(test_get_name, test_get_goal, test_get_state): Add missing free
for job class.
* init/tests/test_control.c (test_emit_event): Directly acess
the number from an NihDBusError
* dbus/com.ubuntu.Upstart.xml: Add a "version" property to obtain
the version of the init daemon, and a "log_priority" property to
get and set the daemon's log priority.
* init/control.c (control_get_version, control_get_log_priority)
(control_set_log_priority): Methods to support the new properties
* init/control.h: Prototypes.
* init/tests/test_control.c (test_get_version)
(test_get_log_priority, test_set_log_priority): Add tests for the
property accessor functions.
2009-07-02 Scott James Remnant <scott@netsplit.com>
* dbus/Upstart.conf: Need to adjust the security configuration
* dbus/upstart.h: And the constants as well.
* dbus/com.ubuntu.Upstart.xml,
* dbus/com.ubuntu.Upstart.Job.xml,
* dbus/com.ubuntu.Upstart.Instance.xml: Now we don't hardcode the
interface name anywhere, we can version it properly.
* init/Makefile.am ($(com_ubuntu_Upstart_OUTPUTS)):
($(com_ubuntu_Upstart_Job_OUTPUTS)):
($(com_ubuntu_Upstart_Instance_OUTPUTS)): Update default interface
names.
* util/Makefile.am ($(com_ubuntu_Upstart_OUTPUTS)):
($(com_ubuntu_Upstart_Job_OUTPUTS)):
($(com_ubuntu_Upstart_Instance_OUTPUTS)): Update here too.
* dbus/Makefile.am (EXTRA_DIST): Make sure we distribute it
* dbus/upstart.h: Add a header file with the usual D-Bus constants.
* init/control.h: Drop CONTROL_ROOT, replace with DBUS_PATH_UPSTART
* init/control.c (control_server_open, control_bus_open)
(control_register_all): Replace CONTROL_* constants with the new ones
(control_get_job_by_name): Use DBUS_INTERFACE_UPSTART when constructing
error names.
* init/job_class.c (job_class_new, job_class_register)
(job_class_unregister): Construct paths using DBUS_PATH_UPSTART
(job_class_get_instance)
(job_class_get_instance_by_name, job_class_start)
(job_class_stop, job_class_restart): Use DBUS_INTERFACE_UPSTART to
construct error names
* init/job.c (job_new): Construct path using DBUS_PATH_UPSTART
(job_finished, job_start, job_stop, job_restart): Use
DBUS_INTERFACE_UPSTART to construct error names.
* init/event.c (event_finished): Use DBUS_INTERFACE_UPSTART to
construct error name.
* init/tests/test_control.c (test_server_open): Don't hardcode
the address, extract the abstract path from the constant.
(test_server_connect, test_bus_open, test_emit_event): Don't
harcode addresses, paths or interfaces - use the constants
* init/tests/test_job_class.c (test_consider, test_reconsider)
(test_register, test_unregister, test_start, test_stop)
(test_restart, test_get_instance, test_get_instance_by_name):
Use the constants instead of harcoding.
(test_new): Derive the expected path from the constant
* init/tests/test_job.c (test_new): Derive the paths from the
constant, check for jobs by that interface constant.
(test_change_state): Use DBUS_INTERFACE_UPSTART_JOB
(test_start, test_stop, test_restart): Use DBUS_INTERFACE_UPSTART_INSTANCE,
and generate errors from DBUS_INTERFACE_UPSTART
* dbus/com.ubuntu.Upstart.xml,
* dbus/com.ubuntu.Upstart.Job.xml,
* dbus/com.ubuntu.Upstart.Instance.xml: Remove the empty symbol
annotation for the interfaces.
* init/Makefile.am ($(com_ubuntu_Upstart_OUTPUTS)):
($(com_ubuntu_Upstart_Job_OUTPUTS)):
($(com_ubuntu_Upstart_Instance_OUTPUTS)): Define the default
interface and build-time instead.
* util/Makefile.am ($(com_ubuntu_Upstart_OUTPUTS)):
($(com_ubuntu_Upstart_Job_OUTPUTS)):
($(com_ubuntu_Upstart_Instance_OUTPUTS)): Likewise for util
2009-06-30 Scott James Remnant <scott@netsplit.com>
* dbus/Upstart.conf: It doesn't make much sense to restrict getting
the values of properties, or looking up jobs or interfaces, so make
these public.
2009-06-23 Scott James Remnant <scott@netsplit.com>
* Makefile.am (SUBDIRS): Add util to the list of sub-directories
again.
* configure.ac (AC_CONFIG_FILES): Generate util/Makefile
* util/Makefile.am (AM_CFLAGS): Append D-Bus CFLAGS
(AM_CPPFLAGS): Make sure the build directory is also in the quoted
include path
(nodist_initctl_SOURCES): Build and link the generated D-Bus
bindings, but don't distribute them
(initctl_LDADD): Drop the libupstart dependency, instead put
libnih-dbus and DBUS_LIBS in there.
(com_ubuntu_Upstart_OUTPUTS, com_ubuntu_Upstart_XML)
($(com_ubuntu_Upstart_OUTPUTS)): Auto-generate D-Bus binding code
to proxy the manager object
(com_ubuntu_Upstart_Job_OUTPUTS, com_ubuntu_Upstart_Job_XML)
($(com_ubuntu_Upstart_Job_OUTPUTS)): Auto-generate D-Bus binding
code to proxy job class objects
(com_ubuntu_Upstart_Instance_OUTPUTS)
(com_ubuntu_Upstart_Instance_XML)
($(com_ubuntu_Upstart_Instance_OUTPUTS)): Auto-generate D-Bus
binding code to proxy job instance objects
(BUILT_SOURCES, CLEANFILES): Built sources have to come first
and be cleaned up
(test_initctl_LDADD): Tests need to be linked to libnih-dbus
and the D-Bus libraries, as well as the auto-generated output
* init/Makefile.am (EXTRA_DIST): Drop the EXTRA_DIST for the
sources, already handled since they're in a different directory
* COPYING: Change licence to version 2 of the GNU GPL.
All files have been updated to reflect this.
* init/paths.h (CONFFILE): Add new macro
* init/Makefile.am (AM_CPPFLAGS): Add CONFFILE definition
(install-data-local): No need to make conf.d or jobs.d
* init/main.c: Only parse CONFFILE (/etc/init.conf) as a
configuration file source and CONFDIR (/etc/init) as a job
configuration source.
* configure.ac: Bump version to 0.6.0
* NEWS: Copy in news from 0.5.3; that release doesn't appear in
this ChangeLog since it was made on a separate branch. Begin
new release.
2009-06-18 Casey Dahlin <cdahlin@redhat.com>
* util/man/initctl.8: Fix formatting of SYNOPSIS
2009-06-18 Scott James Remnant <scott@netsplit.com>
* dbus/com.ubuntu.Upstart.xml, dbus/com.ubuntu.Upstart.Job.xml,
dbus/com.ubuntu.Upstart.Instance.xml: Add a comment to these files
to clarify that you may communicate and interact with Upstart
through these interfaces without restriction. It also makes sense
that these files be copied into software that does so to turn into
their own bindings, so use the FSF permissive licence for them.
2009-06-17 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.5.3
* NEWS: Copy in news from 0.5.2; that release doesn't appear in
this ChangeLog since it was made on a separate branch.
* NEWS: Include 0.3.10 release, which happened from a separate branch.
* init/parse_job.c (stanza_kill, stanza_respawn, stanza_nice)
(stanza_oom): Check errno after using strtol() to avoid overflows.
(stanza_normal, stanza_umask, stanza_limit): Also check with
strtoul() too
* init/tests/test_parse_job.c (test_stanza_kill)
(test_stanza_respawn): Add test cases for the two that don't
check for overflow already.
(test_stanza_limit): Add test for the too large case where we don't
already cope.
* dbus/Upstart.conf: Allow root to obtain properties
* dbus/com.ubuntu.Upstart.Instance.xml: Add name, goal and state
properties to the instance
* init/job.c (job_get_name, job_get_goal, job_get_state): Add methods
to return the property values
* init/job.h: Add prototypes.
* init/tests/test_job.c (test_get_name, test_get_goal)
(test_get_state): Test cases.
* dbus/com.ubuntu.Upstart.Job.xml: Add name, description, author
and version properties to the job
* init/job_class.c (job_class_get_name)
(job_class_get_description, job_class_get_author)
(job_class_get_version): Add methods to return the property values.
* init/job_class.h: Add prototypes
* init/job_process.c (job_process_error_abort): Don't abort() from
a child process, it confuses people; just exit with an interesting
error code (which we ignore anyway).
* dbus/Upstart.conf: Update the D-Bus configuration based on newer
D-Bus recommended practice with a proper deny-by-default D-Bus,
making sure to not use send_interface without send_destination.
Allow introspection as well.
2009-06-17 Jeff Oliver <Jeffrey.Oliver@panasonic.aero>
* init/job_process.c (job_process_spawn): Only attempt to set
the OOM adjustment if set in the class, avoiding issue where /proc
is not mounted for the first job.
2009-06-17 Scott James Remnant <scott@netsplit.com>
* init/tests/test_job_process.c (test_handler): Add test cases for a
respawning job failing while it's post-start or pre-stop processes
are still running while making sure that it still respawns afterwards.
* init/job_process.c (job_process_terminated): To fix it, check for
a running post-start or pre-stop process before checking for a the
respawn. That's not enough because then we won't respawn when the
existing process finishes, so use the goal as a hint.
* init/job.c (job_next_state): Use that hint goal here, remembering
to set the goal back to JOB_START afterwards.
(job_change_goal): Nothing to do in the respawn case
(job_goal_name, job_goal_from_name): Add the new values
* init/job.h (job_goal): Add the respawn goal
* init/tests/test_job.c (test_next_state): Add tests for the respawn
goal
(test_goal_name, test_goal_from_name): Tests for the new values
* configure.ac (AC_CONFIG_FILES): dbus goes before init just in case
we ever do anything to them later
* init/job_class.c (job_class_register, job_class_unregister): Update
name of signal functions that we call.
(job_class_interfaces): No need to declare this separately
* init/job.c (job_register, job_change_state): Update name of signal
functions.
(job_interfaces): Drop, it comes from the generated header now
* init/control.c (manager_interfaces): Drop, comes from the header
as control_interfaces
(control_register_all): Change array name
* init/tests/test_job_class.c,
* init/tests/test_job.c,
* init/tests/test_control.c,
* init/tests/test_blocked.c: Rename conn member of NihDBusMessage
to connection
* dbus/com.ubuntu.Upstart.xml,
* dbus/com.ubuntu.Upstart.Job.xml,
* dbus/com.ubuntu.Upstart.Instance.xml: Use annotation to mark the
methods as async, rather than a namespaced attribute. Omit the
interface symbol.
* init/Makefile.am (AM_CPPFLAGS): Add builddir to the quoted includes
(init_SOURCES): Don't distribute the auto-generated outputs
($(com_ubuntu_Upstart_OUTPUTS))
($(com_ubuntu_Upstart_Job_OUTPUTS))
($(com_ubuntu_Upstart_Instance_OUTPUTS)): Generate using the new
binary tool.
(BUILT_SOURCES): Remind myself why these are BUILT_SOURCES
(MAINTAINERCLEANFILES): Change to ordinary CLEANFILES
(EXTRA_DIST): outputs aren't distributed
2009-05-22 Scott James Remnant <scott@netsplit.com>
* init/tests/test_conf.c: Remove nih/inotify.h include
* COPYING: Change licence from GPL-2+ to GPL-3 only.
2009-05-17 Scott James Remnant <scott@netsplit.com>
* init/tests/test_job.c,
* init/tests/test_job_class.c,
* init/tests/test_control.c: Include nih-dbus/errors.h
2009-05-09 Scott James Remnant <scott@netsplit.com>
* init/init.supp: setenv on tls/i686/cmov
* init/job_class.c (job_class_get_instance, job_class_start)
(job_class_stop, job_class_restart): Clean up the code by using
nih_error_steal()
* init/conf.c (conf_source_reload_file, conf_source_reload_dir):
Steal the error that we stash instead of getting it, otherwise we'll
fail if another one occurs.
* init/conf.c (conf_reload_path): Simply return, no need to re-raise
the error.
* init/job_class.c (job_class_get_instance, job_class_start)
(job_class_stop, job_class_restart): If not ENOMEM, we need to
re-raise the error as a D-Bus one, that means we now have to free
the old error first (saving the msssage)
* init/job_process.c (job_process_error_read): Replace call to
nih_error_raise_again() with nih_error_raise_error()
* init/Makefile.am ($(com_ubuntu_Upstart_OUTPUTS)):
($(com_ubuntu_Upstart_Job_OUTPUTS)):
($(com_ubuntu_Upstart_Instance_OUTPUTS)): Use the Python variant
of nih-dbus-tool for now
2009-03-27 Scott James Remnant <scott@netsplit.com>
* init/tests/test_process.c (test_from_name): Cast -1 to ProcessType
* init/tests/test_job_process.c (test_kill, test_handler): Cast -1
to ProcessType
* init/tests/test_job.c (test_new, test_change_state): Cast -1
to ProcessType
(test_goal_from_name): Cast -1 to JobGoal
(test_state_from_name): Cast -1 to JobState
* init/tests/test_control.c (test_bus_open): Add braces
* init/Makefile.am (tests): Add rule to build test cases
* util/Makefile.am (tests): Likewise
* init/job.c (job_interfaces): Put static first
(job_emit_event): Cast -1 to ProcessType
(job_emit_event): Cast -1 to ProcessType
* init/job_class.c (job_class_interfaces): Put static first.
* init/job_process.c (job_process_kill_timer): Cast -1 to ProcessType
* init/control.c (manager_interfaces): Put static first
* init/Makefile.am (AM_CPPFLAGS): Use -iquote$(srcdir) instead of -I
since we only need it to pick those paths up.
* util/Makefile.am (AM_CPPFLAGS): Likewise.
2009-02-20 Scott James Remnant <scott@netsplit.com>
* util/initctl.c (handle_job_instance_end, handle_job_process)
(handle_job_status_end, handle_event),
* util/shutdown.c (main): No need for new_* temporary variable when
looping over nih_realloc with NIH_MUST.
* util/initctl.c (job_info_output, output_name, handle_job_list)
(handle_job_instance, handle_job_instance_end)
(handle_job_status, handle_job_process, handle_job_status_end)
(handle_event, env_option),
* util/telinit.c (main),
* util/shutdown.c (main, shutdown_now, timer_callback, wall):
* init/event.c (event_init, event_pending_handle_jobs, event_finished),
* init/event_operator.c (event_operator_events),
* init/job.c (job_emit_event, job_name),
* init/job_class.c (job_class_init, job_class_start)
(job_class_stop, job_class_restart),
* init/job_process.c (job_process_run, job_process_error_read)
(job_process_kill),
* init/conf.c (conf_init, conf_source_reload_file)
(conf_reload_path),
* init/control.c (control_init, control_server_connect)
(control_bus_open): Set variable outside of NIH_MUST macro.
* init/event.c (event_pending_handle_jobs): Set variable outside
of NIH_SHOULD macro.
* init/Makefile.am ($(com_ubuntu_Upstart_OUTPUTS)):
($(com_ubuntu_Upstart_Job_OUTPUTS)):
($(com_ubuntu_Upstart_Instance_OUTPUTS)): Update expected path
of nih-dbus-tool
* configure.ac: Create nih-dbus-tool Makefile
* Makefile.am (SUBDIRS): Build in nih-dbus-tool
2009-01-29 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.5.2
* NEWS: Begin 0.5.2
* NEWS: Copy in news from 0.5.1; that release doesn't appear in
this ChangeLog since it was made on a separate branch.
* init/tests/test_blocked.c (test_new),
* init/tests/test_control.c (test_get_job_by_name)
(test_get_all_jobs, test_emit_event),
* init/tests/test_event.c (test_finished),
* init/tests/test_job.c (test_change_state),
* init/tests/test_job_class.c (test_get_instance)
(test_get_instance_by_name, test_get_all_instances): Continue the
battle with the gcc optimiser which declares variables first used
inside TEST_ALLOC_FAIL as used uninitialized.
* init/parse_job.c (parse_exec, parse_script, stanza_instance)
(stanza_description, stanza_author, stanza_version)
(stanza_start, stanza_stop, stanza_chroot, stanza_chdir):
Unreference members when replacing them instead of freeing; not
strictly necessary but the style is the thing.
* init/job_process.c (job_process_terminated): Unreference the
kill timer instead of freeing
* init/job_class.c (job_class_get_instance): Use nih_local for
instance environment and name
(job_class_start, job_class_stop, job_class_restart):
Unreference job environment instead of freeing
* init/job.c (job_change_state, job_start, job_stop, job_restart):
Unreference job environment instead of freeing
(job_name): Discard job name in case a reference was taken.
* init/event.c (event_pending_handle_jobs): Unreference the job
environment instead of freeing
* init/environ.c (environ_add): should unreference the old environment
string in case anyone took a ref elsewhere
(environ_set): use nih_local for str
(environ_expand_until): Should set *str to NULL if we free it,
just in case.
* init/conf.c (conf_source_reload): File should be unreferenced,
not freed.
(conf_source_reload_file): Use nih_local for dpath
(conf_delete_handler): Watch and file should be unreferenced,
not freed.
(conf_reload_path): File should be unreferenced, not freed;
use nih_local for file buffer
* init/blocked.c (blocked_new),
* init/conf.c (conf_source_new, conf_file_new),
* init/event.c (event_new),
* init/event_operator.c (event_operator_new),
* init/job.c (job_new),
* init/job_class.c (job_class_new): No need to cast function
argument to nih_alloc_set_destructor()
* init/tests/test_job_process.c (test_handler): We can't just
assume that our child is sitting at the signal otherwise we might
end up sending the CONT signal before it's even stopped. Use
waitid() to wait for the child to stop first.
* init/init.supp: More expressions for environment memory which
valgrind can't deal with
* init/conf.c (conf_source_reload): The ConfFile destructor has
side-effects that involve the iteration of the sources and their
files, so we can't simply call it while iterating because of the
cursor. Move the sources into a deleted list first, and delete
them from there.
* init/conf.h: Fix prototype.
* init/tests/test_conf.c (test_source_reload_job_dir): Test pointers
with TEST_EQ_P not TEST_EQ
2009-01-28 Scott James Remnant <scott@netsplit.com>
* init/job_class.c (job_class_start): We can't create the blocked
until we know we're going to block, otherwise we could ref and unref
the message (freeing it). Wait until the job is created, which
means we can't fail to create the blocked item (we'll already have
announced the new instance).
(job_class_stop, job_class_restart): For consistency, don't fail
if OOM when making blocked.
* init/tests/test_job.c (test_new): Initialise a bunch of subsystems
outside of TEST_ALLOC_FAIL
* init/environ.c (environ_add): We can't allocate nih_local with
a context, it won't be freed; so don't, but then remember to
reference it when we do just use it.
* init/event.c (event_pending_handle_jobs): Must reset the start_on
operator in case of error.
* init/job_process.c (job_process_kill_timer): Oops, move the
assert that we have a process pid to after we know which process
we have.
* init/tests/test_job_process.c (test_run): Initialise the
error context and NihIo outside of TEST_ALLOC_FAIL
(test_kill): Initialise timers and the event system.
* init/init.supp: Reference from the jobs hash to the bins is
still reachable, obviously; as is the string inside job_name()
either way it is allocated
* init/tests/test_parse_job.c (test_parse_job): Initialise the
error context outside of TEST_ALLOC_FAIL
* init/init.supp: Update suppressions for new nih_alloc()
* init/job_process.c (job_process_run): Had the shell variable
setting round the wrong way, now it should be ok.
* init/tests/test_blocked.c (test_new): in the case of allocation
failure, the message should not be referenced; which we test by
trying to discard it and seeing whether that works.
* init/job.c (job_emit_event): event_new() only references the
environment now, so use nih_local to make sure we clean it up
if that doesn't happen
* init/job.h (Job): Add kill_process member
* init/job.c (job_new): Initialise to -1
* init/job_process.c (job_process_kill): Store the process to be
killed in the kill_process member for the timer, since we can't
pass two sets of data. Assert that it's not set to anything, this
all needs fixing, obviously.
(job_process_kill_timer): Take the job as the data argument,
eliminating the need for nih_alloc_parent(). Sanity check the job
and reset kill_timer and kill_process when done.
(job_process_terminated): Clear the kill_process field too.
* init/tests/test_job.c (test_new): Check it's -1
(test_change_state): Check kill_process is set to PROCESS_MAIN
when active, or -1 when not.
* init/tests/test_job_process.c (test_kill): Make sure the
kill_process member is set and cleared.
(test_handler): Set the kill_process member for the timer and make
sure it's cleared when appropriate.
* init/job_class.c (job_class_start, job_class_stop)
(job_class_restart): Use nih_local to eliminate nih_alloc_reparent,
and to clean up some of the code too.
* init/job_class.c: Update documentation to match new nih_alloc()
* init/parse_job.c (parse_on_operator, parse_on_collect):
Use an nih_ref/nih_unref pair instead of nih_alloc_reparent; this
is not ideal, but then this code is rather messy and leaves a lot
of allocated data attached to the object on the assumption that
it will be thrown away.
* init/event_operator.c: Update documentation to match new nih_alloc()
(event_operator_match): Use nih_local on expanded value.
(event_operator_environment): Make evlist nih_local, it will be
referenced by the environment array on success
* init/event_operator.c (event_operator_new): Reference the
event instead of reparenting it.
* init/event.c: Update documentation to match new nih_alloc()
(event_finished): Use nih_local to tidy up a slight bit.
* init/event.c (event_new): Reference the event, don't reparent
(event_pending_handle_jobs): Use nih_local for environment array
and for the job name, damn I love this thing. Reference the array
into the job to avoid freeing.
* init/parse_job.c (parse_job): Update documentation to match
new nih_alloc()
(parse_process, parse_on_operator, stanza_start, stanza_stop)
(stanza_expect, stanza_kill, stanza_respawn, stanza_normal)
(stanza_session, stanza_console, stanza_nice, stanza_umask)
(stanza_oom, stanza_limit): Use nih_local for all the temporary
arguments where we can.
* init/parse_job.c (parse_on_operand, stanza_env, stanza_export)
(stanza_emits): Make temporary string variables use nih_local,
this gives us a massive code clean-up and makes nih_str_array_addp
safe to take a reference.
* init/job_process.c (job_process_run): Make argv, env, script and
cmd all use nih_local, this cleans up the code a little and makes
nih_str_array_addp safe to take a reference.
* init/environ.c: Update documentation to match new nih_alloc()
* init/tests/test_job_process.c (test_run): Check that trailing
newlines are ignored when running a script (can verify r1025 is
fixed with gdb)
* init/tests/test_environ.c (test_expand): Add a test case for the
bug fixed in r1027, the implicit case of the gap in the environment
string being the same size as the value replacing it.
* init/environ.c (environ_add): Use nih_local for new_str, making
the code paths a little simpler and ensuring we pass something that
can be referenced to nih_str_array_addp()
* init/tests/test_event.c (test_new): Make sure that env is an
orphan with TEST_ALLOC_ORPHAN.
* init/tests/test_event_operator.c (test_operator_new): Make sure
that env is an orphan with TEST_ALLOC_ORPHAN.
(test_operator_copy): Drop pointless NULL parent check.
* init/tests/test_control.c: Include limits.h
* init/blocked.c (blocked_new): Take a reference to the message,
otherwise it will be freed; we free the Blocked structure when we're
done, so will automatically unref the message.
* init/tests/test_blocked.c (test_new): Add tests to make sure the
reference is taken.
* init/tests/test_job.c (test_start, test_stop, test_restart):
Make sure the message is referenced when an error is not returned
but not referenced when one is.
* init/tests/test_job_class.c (test_start, test_stop)
(test_restart): Make sure the message is referenced when an error
is not returned but not referenced when one is.
* init/tests/test_control.c (test_emit_event): Make sure that
the message is referenced.
* init/tests/test_blocked.c: Change nih/dbus.h include to
nih-dbus/dbus_message.h
* init/tests/test_control.c: Change nih/dbus.h include to error,
connection and object; include D-Bus test macros.
* init/tests/test_job.c: Change nih/dbus.h include to error, message
and object; include D-Bus test macros
* init/tests/test_job_class.c: Change nih/dbus.h include to error,
message and object; include D-Bus test macros
* init/job_class.h: Change nih/dbus.h include to
nih-dbus/dbus_message.h and include the actual D-Bus header
* init/job_class.c: Change nih/dbus.h include to error, message,
object and util.
* init/job.h: Change nih/dbus.h include to nih-dbus/dbus_message.h
and include the actual D-Bus header
* init/job.c: Change nih/dbus.h include to error, message, object
and util.
* init/control.h: Change nih/dbus.h include to nih-dbus/dbus_message.h
and include the actual D-Bus header
* init/control.c: Change nih/dbus.h include to error, connection,
message and object includes.
* init/blocked.h: Change nih/dbus.h include to nih-dbus/dbus_message.h
* init/blocked.c: Change nih/dbus.h include to nih-dbus/dbus_message.h
2009-01-27 Scott James Remnant <scott@netsplit.com>
* init/Makefile.am: Update paths to libnih-dbus dependencies.
2009-01-26 Scott James Remnant <scott@netsplit.com>
* configure.ac (AC_CONFIG_FILES): Add nih-dbus sub-directory
* Makefile.am (SUBDIRS): Add nih-dbus sub-directory
* configure.ac: Bump copyright to 2009
* configure.ac: Matching libnih, we now mandate libtool 2.2.x
* HACKING: Update dependency requirement to 2.2.4
* init/init.supp: Adjust suppression for glibc 2.8
* init/tests/test_event.c (test_finished): Remove erroneous test
of free'd memory.
* configure.ac: Bump version to 0.5.1
* init/tests/test_event_operator.c (test_operator_handle): Add a
test for duplicate events when already matched.
* init/event_operator.c (event_operator_handle): Skip if already
matched.
* README: Update features and requirements.
* NEWS: Copy in news from 0.5.0; that release doesn't appear in
this ChangeLog since it was made on a separate branch.
2009-01-26 Casey Dahlin <cdahlin@redhat.com>
* init/environ.c (environ_expand_until): Handle the implicit case
of the gap in the string being the same size of the value.
* init/job_process.c (job_process_handler): Handle the case of a
child being continued by a signal, otherwise we'll assert.
* init/job_process.c (job_process_run): Double-check that the
newline(s) we see are at the end of the script before stripping,
since we can fall through if the newline is mid-script but /dev/fd
isn't mounted.
2008-07-05 Scott James Remnant <scott@netsplit.com>
* TODO: Update.
2008-07-01 Scott James Remnant <scott@netsplit.com>
* init/Makefile.am ($(com_ubuntu_Upstart_OUTPUTS)):
($(com_ubuntu_Upstart_Job_OUTPUTS)):
($(com_ubuntu_Upstart_Instance_OUTPUTS)): Must be newer than the
source for the dbus tool, and ensure the dbus tool is built
2008-06-30 Scott James Remnant <scott@netsplit.com>
* init/Makefile.am: Update along with libnih so that we leave the
D-Bus bindings in the dist tarball, meaning Python is no longer a
build-dependency.
2008-06-11 Scott James Remnant <scott@netsplit.com>
* Makefile.am (SUBDIRS): List dbus before init in case we need to
generate anything in that directory later on.
* Makefile.am (SUBDIRS): List po last so that update-po is run after
generating any sources.
2008-06-08 Scott James Remnant <scott@netsplit.com>
* init/Makefile.am (EXTRA_DIST): Ship the built sources, don't
clean them.
(maintainer-clean-local): Well, not unless maintainer-clean anyway
* init/job.c, init/job_class.c: Add missing errno.h include
* dbus/com.ubuntu.Upstart.Job.xml (GetInstance): Add method to get
an instance name in the same basic manner as start and stop would,
though this one's synchronous.
* init/job_class.c (job_class_get_instance): Implementing by copying
the relevant bit of Stop.
* init/job_class.h: Add prototype.
* init/tests/test_job_class.c (test_get_instance): Add tests.
* TODO: Continue to document the C&P madness.
* init/conf.c (conf_reload_path): Read file directly into memory,
not using mmap.
* compat/sysv/reboot.c, compat/sysv/runlevel.c, compat/sysv/shutdown.c,
* compat/sysv/telinit.c: Move into the util directory; we're going
to support limited SysV-a-like commands without full compatibility
which is what we always did, and I'm not going to worry about adding
others.
* compat/sysv/man/reboot.8, compat/sysv/runlevel.8,
* compat/sysv/man/shutdown.8, compat/sysv/telinit.8: Move as well.
* compat/sysv/Makefile.am, util/Makefile.am: Merge.
* configure.ac: Remove the (commented out) compat/sysv and logd
Remove the --enable-compat option.
* Makefile.am (SUBDIRS): Remove (commented out) compat/sysv and logd
* logd/Makefile.am, logd/main.c, logd/man/logd.8, logd/jobs.d/logd.in:
Consign logd to oblivion. We haven't supported it for ages, it has
non-working issues, and there's got to be a better way to do this.
* TODO: Update.
* init/job.c (job_change_goal): Adjust the documentation. After
careful thought, there's no way this can return after freeing the
job, since it'll either block on an event, a process or do nothing.
* init/job.c (job_start, job_stop, job_restart): Clear the start
and stop environment, shouldn't necessarily make a difference, but
it pays to be consistent.
* dbus/com.ubuntu.Upstart.Job.xml (Start, Stop, Restart): Add methods
to control jobs, all take an environment array and both Start and
Restart return an instance path so properties, etc. can be obtained
afterwards.
* init/job_class.c (job_class_start, job_class_stop)
(job_class_restart): Add the code for the top halves of the methods
* init/job_class.h: Add prototypes for the new methods.
* init/job.c (job_finished): And the bottom halves go here.
* init/tests/test_job_class.c (test_start, test_stop)
(test_restart): Add test cases for the methods.
* init/blocked.h (blocked_type): Add enums for the new methods.
* init/blocked.c (blocked_new): Handle the new methods here.
* init/tests/test_blocked.c (test_new): Add add tests for handling.
2008-06-07 Scott James Remnant <scott@netsplit.com>
* init/job_process.c (job_process_terminated): Don't check the goal
to see whether the main process was allowed to terminate, check the
state. A termination is only not a failure if we're on the KILLED
state (ie. we killed it), otherwise it can still be a failure even
if it was going to stop anyway.
* init/tests/test_job_process.c (test_handler): Add a test case.
* init/control.c (control_emit_event): Use environ_all_valid here(),
also reorder the blocking stuff to be less strange, it's ok to free
environment.
* init/tests/test_control.c (test_emit_event): The event array should
be a child of message, which means it doesn't matter if the function
we call frees it.
* init/environ.c (environ_all_valid): Add a validation function for
external input.
* init/environ.h: Add prototype.
* init/tests/test_environ.c (test_all_valid): Test function.
* init/environ.c: Note that we can call this in a loop with OOM,
since the resulting table will always be the same.
* init/event_operator.c (event_operator_environment): Use
environ_append(), and while we're at it, there's no reason this should
use NIH_MUST.
* init/event_operator.h: Adjust prototype.
* init/tests/test_event_operator.c (test_operator_environment): Allow
for failure.
* init/event.c (event_pending_handle_jobs): Call with NIH_MUST,
which is actually safe.
* init/job_class.c (job_class_environment): Use environ_append()
* init/environ.c (environ_append): There are multiple cases where we
append one environment table onto another, so we should have a
function to do that.
* init/environ.h: Prototype for it.
* init/tests/test_environ.c (test_append): Test the new function.
* init/job_process.c (job_process_run): Invert the logic; we nearly
always want to pass the script with /dev/fd/NNN. The only times we
don't are if it doesn't exist, or if we're dealing with a single-line
shell script.
* init/tests/test_job_process.c (test_run): Update test cases to
only expect an argv-execution for single-line scripts.
* init/job.c (job_restart): Wrote the blocking bit slightly weirdly
without neededing to, so leave it as it should be.
* TODO: Update.
* dbus/com.ubuntu.Upstart.Instance.xml (Start, Stop, Restart): Add
simple instance control methods, these only change the goal of an
existing instance - thus cannot pass environment.
* init/job.c (job_start, job_stop, job_restart): Add methods, which
look spookily similar to each other, except for the subtle yet
important differences.
(job_finished): Implement bottom halves.
* init/job.h: Add prototypes.
* init/tests/test_job.c (test_start, test_stop, test_restart): Add
tests for the new methods.
* init/blocked.h (blocked_type): Add enums for methods.
* init/blocked.c (blocked_new): Handle methods here too
* init/tests/test_blocked.c (test_new): Add tests for them.
2008-06-06 Scott James Remnant <scott@netsplit.com>
* init/blocked.h (blocked_type): Having a single message type won't
work for the job cases, so expand to have many.
* init/blocked.c (blocked_new): We'll just have to list them all here.
* init/control.c (control_emit_event): Happily we create them
individually anyway.
* init/event.c (event_finished): And since we have to handle them
individually, it'll actually protect us replying to the wrong one.
* init/tests/test_conf.c (test_source_reload): Clean up the temporary
directory.
* init/tests/test_control.c (test_reload_configuration): That goes
for this one too.
* init/tests/test_control.c (my_connect_handler): Use TEST_DBUS_MESSAGE
instead of a pop/read/write loop.
(test_emit_event): Renamed TEST_DBUS_CONN to TEST_DBUS_OPEN.
* init/tests/test_job.c (test_new, test_register)
(test_change_state): Use TEST_DBUS_OPEN and TEST_DBUS_CLOSE to setup
and tear down D-Bus connections and TEST_DBUS_MESSAGE instead of
a loop.
* init/tests/test_job_class.c (test_consider, test_reconsider)
(test_register, test_unregister): Likewise.
* init/control.c (control_get_job_by_name): Sanity check the name
of a job in the same way; we don't need to sanity check the instance
name because "" is valid (and the default for singletons).
* init/tests/test_control.c (test_get_job_by_name): Test.
* dbus/com.ubuntu.Upstart.xml (EmitEvent): Add an asynchronous
method to emit an event, providing the name and accompanying
environment. No return value, it either works or you get an
error.
* init/control.c (control_emit_event): Implement top half of the
method, blocking the message in the event.
* init/control.h: Add prototype.
* init/event.c (event_finished): Implement the bottom half which
sends the reply or error, these are actually tested along with
the top for sanity reasons.
* init/tests/test_control.c (test_emit_event): Test the various
ways the method may be used and abused; the async nature means
we actually need a real D-Bus server to do this.
* TODO: Update.
* init/event.c (event_new): There's no reason this shouldn't be
allowed to return insufficient memory, so do so.
(event_finished): Wrap call.
* init/tests/test_event.c (test_new): Add alloc failed test.
* init/job.c (job_emit_event): Must create the event.
* init/main.c (main, cad_handler, kbd_handler, pwr_handler): Wrap
with NIH_MUST
2008-06-05 Scott James Remnant <scott@netsplit.com>
* TODO: Update.
* init/job.c (job_unblock): Rename to job_finished, since this
does not behave like event_unblock but more like event_finished
(job_change_state, job_failed): Change name in call.
* init/job.h: Update prototype.
* init/tests/test_job.c (test_unblock): Rename to test_finished
* init/event.c (event_pending_handle_jobs): Update calls here.
* init/job.h (Job): Rename blocked to blocker to match event, since
it has the same use as event->blockers except it's a toggle
* init/job.c (job_new, job_change_state): Rename where used
* init/event.c (event_finished): Rename here also since its reset
* init/tests/test_job.c, init/tests/test_job_process.c,
* init/tests/test_event.c: Rename in test cases too.
* init/job.c (job_emit_event): Add a Blocked record to the event's
blocking list for the starting and stopping events.
* init/tests/test_job.c (test_emit_event): Add tests for the record
being added to the list with the right details.
(test_change_goal): Make sure that a Blocked record is added
(test_change_state): Make sure that Blocked records are added
* init/tests/test_job_process.c (test_handler): Also make sure
that Blocked records are added.
* init/event.c (event_finished): Clear jobs referenced in the
blocking list, rather than iterating the entire jobs hash.
(event_finished_handle_jobs): Drop this function.
* init/tests/test_event.c (test_finished, test_finished_handle_jobs):
Merge tests again and test using both the blocking list and job's
blocked member.
* init/event.h (event): Add blocking member.
* init/event.c (event_new): Initialising blocking list.
* init/tests/test_event.c (test_new): Make sure it's initialised
to an empty list.
* init/tests/test_job_process.c (test_handler): Update tests to use
Blocked.
* init/event.c (event_pending_handle_jobs): Collect environment
and events independantly, which means we don't have to worry about
the list contents or freeing them up in case of error.
* init/event_operator.c (event_operator_events): Fix parent.
* init/tests/test_event.c (test_pending_handle_jobs): Update tests.
* init/init.supp: Update collect suppression.
* init/event_operator.c (event_operator_collect): Break in two.
(event_operator_environment): Collect the environment from the event,
appending the list of event names if necessary.
(event_operator_events): Block events and pass them to the
given list.
* init/event_operator.h: Update prototypes.
* init/tests/test_event_operator.c (test_operator_collect): Also
split into two new functions
(test_operator_environment, test_operator_events): Adjust
* init/event_operator.c (event_operator_collect): Placed Blocked
structures in the list, rather than ordinary entries; I strongly
suspect that while it's nice to iterate the operator tree only once,
this needs to be three functions really.
* init/tests/test_event_operator.c (test_operator_collect): Update
test suite.
* init/job.h (Job): Make blocking a statically defined list.
* init/job.c (job_new): Initialise rather than setting to NULL.
(job_unblock): Assume that blocking members are Blocked structures
and that the list itself is always iterable.
* init/tests/test_job.c (test_new): Check the list is empty, rather
than NULL.
(test_change_state, test_failed, test_unblock): Change tests cases
to expect blocking to always be present, and create members as Blocked
structures.
* init/blocked.c (blocked_new): Set destructor (forgotten)
* init/init.supp: Add setenv, which has crept in
* init/blocked.h: Header containing enum, struct and prototype.
* init/blocked.c (blocked_new): Function to allocate the structure
with the right details.
* init/tests/test_blocked.c (test_new): Tests for the new function.
* init/Makefile.am (init_SOURCES): Compile using blocked.c and header
(TESTS): Build blocked test suite
(test_process_LDADD, test_job_class_LDADD)
(test_job_process_LDADD, test_job_LDADD, test_event_LDADD)
(test_event_operator_LDADD, test_parse_job_LDADD)
(test_parse_conf_LDADD, test_conf_LDADD, test_control_LDADD):
Link blocked.o to most test suites.
(test_blocked_SOURCES, test_blocked_LDFLAGS, test_blocked_LDADD):
Details for test suite.
* init/main.c: Also remove SIGTERM handling, we don't re-exec
properly and this is a dangerous signal to use anyway.
(term_handler): Drop function.
* init/main.c: Remove handling for stop/cont; there's no reason
a user should be able to pause the event queue.
(stop_handler): Drop function.
* init/event.c (event_poll): Remove paused handling.
* init/control.c: Fix doc string.
* dbus/com.ubuntu.Upstart.xml (ReloadConfiguration): Add method
that's effectively the same as the HUP signal.
* init/control.c (control_reload_configuration): Unsurprisingly,
the implementation is identical.
* init/control.h: Add prototype.
* init/tests/test_control.c (test_reload_configuration): Make sure
the method works as expected.
(test_get_job_by_name, test_get_all_jobs): Add missing free calls for
message in cases of out of memory.
* dbus/com.ubuntu.Upstart.xml (JobAdded, JobRemoved): Add signals
for when new jobs are added to the known list and when existing jobs
are removed, this allows GUIs to always show an up-to-date list.
* dbus/com.ubuntu.Upstart.Job.xml (InstanceAdded, InstanceRemoved):
Also add matching signals for when instances are added to the list
for a job and when they're removed again.
* init/job_class.c (job_class_register): Emit the JobAdded signal
for this job when registering if the new signal argument is TRUE;
pass on the signal argument to job_register()
(job_class_add): Emit signals when registering jobs with existing
connections.
(job_class_unregister): Emit signals when unregistering a job.
* init/job.c (job_register): Likewise, emit the InstanceAdded signal
for the job class if the new signal argument is TRUE.
(job_new): Emit signals when registering instances with existing
connections.
(job_change_state): Emit the instance removed signal when destroying
an inactive instance.
* init/job_class.h, init/job.h: Add signal argument to prototypes
* init/control.c (control_register_all): When registering job classes
on a new connection, do not emit a signal since they will already
exist at the point when the name appears on the bus or the connection
is complete.
* init/tests/test_control.c (test_bus_open): Add comment that we
are testing for signal non-emission already with the fake server,
since it was this test that actually made me realise we had to
not emit them :p
* init/tests/test_job_class.c (test_register): Test that the signal
is emitted when signal is TRUE and not emitted when signal is FALSE
(test_unregister): Test that the JobRemoved signal is emitted
(test_get_instance_by_name, test_get_all_instances): Free message
if allocation failed.
(test_consider, test_reconsider): Test that the JobAdded and
JobRemoved signals are emitted (or not) when appropriate.
* init/tests/test_job.c (test_register): Make sure that the
InstanceAdded signal is emitted when TRUE is passed, and not when
FALSE is passed.
(test_new): Make sure the InstanceAdded signal is emitted when the
job is registered on the bus.
(test_change_state): Make sure the InstanceRemoved signal is sent
when deleting an instance.
2008-06-02 Scott James Remnant <scott@netsplit.com>
* init/tests/test_job.c (test_new, test_register): Also use a private
dbus server to avoid session bus problems.
* init/tests/test_job_class.c (test_consider, test_reconsider)
(test_register, test_unregister): Use a private dbus server instead
of connecting to the session bus, which might not be there.
* init/tests/test_control.c (test_disconnected): Simplify using a
private dbus server rather than faking one.
* init/tests/test_control.c (test_bus_close): Don't rely on being
able to connect to the various buses, instead use a special private
one.
2008-06-01 Scott James Remnant <scott@netsplit.com>
* dbus/com.ubuntu.Upstart.Job.xml (GetAllInstances): And also add
a similar method to return the object path of all instances of a
particular job.
* init/job_class.c (job_class_get_all_instances): Implement the
method, pretty much the same as the other.
* init/job_class.h: Add prototype.
* init/control.c: Fix comment.
* init/tests/test_control.c (test_get_all_jobs): Ensure that the
individual paths are children of the array.
* dbus/com.ubuntu.Upstart.xml (GetAllJobs): Add method to return
the object path of all known jobs.
* init/control.c (control_get_all_jobs): Implement the method,
somewhat simple happily.
* init/control.h: Add prototype for the method.
* init/tests/test_control.c (test_get_all_jobs): Test that the
right data is returned.
* dbus/com.ubuntu.Upstart.xml, dbus/com.ubuntu.Upstart.Job.xml,
* dbus/com.ubuntu.Upstart.Instance.xml: Add libnih XML NS to the
files so that we can tag methods as sync or async later.
* init/control.c (control_get_job_by_name): Remove const from
return parameter.
* init/control.h: Update prototype.
* init/tests/test_control.c (test_get_job_by_name): Remove const
from path type.
* init/job_class.c (job_class_get_instance_by_name): Remove wrong
const from parameter now that we've fixed the bindings generator.
* init/job_class.h: Update prototype to match.
* init/tests/test_job_class.c (test_get_instance_by_name): Change
type of path to match.
* HACKING (Dependencies): clarify that autoreconf and configure need
to be run for libnih first.
* init/Makefile.am (test_process_LDADD, test_job_class_LDADD)
(test_job_process_LDADD, test_job_LDADD, test_event_LDADD)
(test_event_operator_LDADD, test_parse_job_LDADD)
(test_parse_conf_LDADD, test_conf_LDADD, test_control_LDADD): Link
the auto-generated D-Bus code in, otherwise the tests won't be
complete.
2008-05-24 Scott James Remnant <scott@netsplit.com>
* HACKING: Changed branch location again, of both upstart and
libnih.
2008-05-16 Scott James Remnant <scott@netsplit.com>
* init/job_class.c (job_class_consider, job_class_reconsider): Find
the best class first and compare against the current class before
acting, this avoids the re-register jump every time a job stops.
(job_class_select): Rename to job_class_add() since this is takes
a class and is the direct opposite to job_class_remove().
2008-05-15 Scott James Remnant <scott@netsplit.com>
* init/event.c (event_new): We can't rely on the event poll function
being the last in the main loop, it's often the first, so after
adding an event to the queue ensure the loop is iterated at least
once so that the event poll occurs for it.
2008-05-09 Scott James Remnant <scott@netsplit.com>
* TODO (Anytime): Update.
* dbus/com.ubuntu.Upstart.Instance.xml: format to match others
* dbus/com.ubuntu.Upstart.Job.xml (GetInstanceByName): Add method
* init/job_class.c (job_class_get_instance_by_name): Implementation.
* init/job_class.h: Add prototype.
* init/tests/test_job_class.c (test_get_instance_by_name): Tests
for new method.
* init/job_class.h (JobClass): Make instances a hash table.
* init/job_class.c (job_class_new): Initialise instances as a hash
table now.
(job_class_register): Iterate instances as hash table.
(job_class_remove): Slightly odd construct needed to return FALSE
if there's anything in the hash table.
(job_class_unregister): Likewise to assert on no instances.
* init/tests/test_job_class.c (test_new): Check that instances is
now a hash table.
* init/job.h (Job): Make name the first member.
* init/job.c (job_new): Add to instances as hash table.
(job_instance): Drop entirely, replaced by a hash lookup.
* init/tests/test_job.c (test_instance): Drop.
* init/job_process.c (job_process_find): Iterate instances as a
hash table.
* init/event.c (event_pending_handle_jobs)
(event_finished_handle_jobs): Iterate instances as hash table.
(event_pending_handle_jobs): Replace job_instance call with an
ordinary hash lookup.
* init/tests/test_event.c: Update to use hash table.
* init/tests/test_conf.c: Update instances stealing for hash table
* init/job_class.c (job_class_new): initialise instance to the
empty string.
* init/tests/test_job_class.c: Update job_new() calls.
(test_new): Check instance against the empty string.
* init/job.c (job_new): name may no longer be NULL.
* init/tests/test_job.c: Update job_new() calls.
(test_instance): Reset back to "" when done.
* init/event.c (event_pending_handle_jobs): Always expand the
name, since the class->instance is always non-NULL.
* init/tests/test_event.c: Update job_new calls.
* init/tests/test_conf.c: Update job_new calls.
* init/tests/test_job_process.c: Update job_new calls.
* init/job.c (job_new): Singleton jobs have a fixed name of "",
rather than a NULL name, and a D-Bus name of "_".
(job_instance): Which rather simplifies this function (in fact,
it makes this function look like a common one).
(job_emit_event): Always set INSTANCE variable.
(job_name): Still distinguish in output, to avoid ugly "()" but
check character rather than NULL.
* init/tests/test_job.c (test_new): Check name is set to ""
and path to ".../_"
(test_change_state, test_emit_event): Update test cases to assume
an empty INSTANCE variable
(test_instance): Update to pass "" instead of NULL.
* init/job_process.c (job_process_run): Always set UPSTART_INSTANCE
* init/tests/test_job_process.c (test_run): Always assume an
UPSTART_INSTANCE variable, it may just be empty.
* init/tests/test_event.c (test_pending_handle_jobs): Expect
the name to be set to the empty string.
* init/Makefile.am (com.ubuntu.Upstart.c com.ubuntu.Upstart.h)
(com.ubuntu.Upstart.Job.c com.ubuntu.Upstart.Job.h)
(com.ubuntu.Upstart.Instance.c com.ubuntu.Upstart.Instance.h):
Drop setting of data-type, turns out it doesn't work anyway.
* dbus/Upstart.conf: Add configuration file.
* dbus/Makefile.am (dbussystemdir, dist_dbussystem_DATA): Install
the configuration file into the right place.
* dbus/com.ubuntu.Upstart.xml (GetJobByName): Add method
* init/control.c (control_get_job_by_name): Implementation.
* init/control.h: Prototype.
* init/tests/test_control.c (test_get_job_by_name): Test the
method using a fake message.
2008-05-08 Scott James Remnant <scott@netsplit.com>
* dbus/com.ubuntu.Upstart.xml, dbus/com.ubuntu.Upstart.Job.xml,
* dbus/com.ubuntu.Upstart.Instance.xml: Add DTDs.
* init/control.c (manager_interfaces): Export the general
com.ubuntu.Upstart interface
* init/job_class.c (job_class_interfaces): Export the
com.ubuntu.Upstart.Job interface
* init/job.c (job_interfaces): Export the
com.ubuntu.Upstart.Instance interface
* init/Makefile.am (BUILT_SOURCES)
(com.ubuntu.Upstart.c com.ubuntu.Upstart.h)
(com.ubuntu.Upstart.Job.c com.ubuntu.Upstart.Job.h)
(com.ubuntu.Upstart.Instance.c com.ubuntu.Upstart.Instance.h):
Generate C code and header files from the XML files which produce
object bindings.
(init_SOURCES): Link the built sources.
(CLEANFILES): Clean them up afterwards
* dbus/com.ubuntu.Upstart.xml: Initially empty description for
manager object interface(s).
* dbus/com.ubuntu.Upstart.Job.xml: Initially empty description
for job class object interface(s).
* dbus/com.ubuntu.Upstart.Instance.xml: Initially empty
description for job instance object interface(s).
* dbus/Makefile.am: Distribute the three interface files,
they're used as sources elsewhere.
* configure.ac (AC_CONFIG_FILES): Generate dbus/Makefile
* Makefile.am (SUBDIRS): Descend into the dbus sub-directory.
* init/job_class.c (job_class_consider, job_class_reconsider):
Separate out the actual meat of the functions, since it's largely
duplicated between the two. This makes the difference between
the two functions clearer, consider always stages an election
no matter which is registered, reconsider only stages an election
if the current class is registered.
(job_class_select, job_class_remove): Functions containing the
common code, which now also handle registering and unregistering
the class with D-Bus. Here is the right place, not in new, since
we only export the current best class of a given name.
(job_class_register, job_class_unregister): Function to register
a job and its instances, and to unregister a job (we assert that
there must be no instances for us to do this).
* init/job_class.h: Add prototypes.
* init/tests/test_job_class.c (test_consider, test_reconsider):
Check that D-Bus registration and unregistration happens as
expected.
(test_register, test_unregister): test on their own.
* init/job.c (job_new): Register instances with D-Bus, since
instances can only ever exist for active classes, all instances
are always registered on the bus.
(job_register): Function to register an instance on the bus.
* init/job.h: Add prototype.
* init/tests/test_job.c (test_new): Test creating a job with an
active d-bus connection, which should have it registered.
(test_register): Test registration on its own.
* init/control.c (control_register_all): Make this always succeed,
and register existing jobs on the new connection.
(control_server_connect, control_bus_open): registration is
always successful.
* init/tests/test_control.c (test_server_connect, test_bus_open):
Test with existing jobs when we get a connection or create the
bus connection, ensure that the jobs and instances are registered.
* init/tests/test_job.c (test_change_state): Check for a bug where
a job with multiple instances will be freed when one instance is
deleted rather than the last instance.
* init/job.c (job_change_state): Add debugging messages when we
destroy a job that's no longer the current one or an instance
that's no longer active; also ensure that we never destroy a job
that's the current one.
* init/event.c (event_pending_handle_jobs): Add a debugging message
when we create a new instance of a job.
* init/conf.c (conf_file_destroy): Add a debugging message when
we destroy a job that's no longer the current one.
2008-05-07 Scott James Remnant <scott@netsplit.com>
* init/control.c (control_server_open, control_server_close)
(control_server_connect): Create and manage a listening d-bus server
that is used for private direct connections to Upstart for when the
d-bus daemon is not available. Each new connection has the same
objects as the d-bus system bus, they only differ in their method.
(control_conns, control_init): Cache the open connections, including
the bus daemon and any private connections; we'll iterate this list
when sending signals.
(control_bus_open): Store connection in the list, don't worry about
setting close-on-exec, we check that by test case and rely on d-bus
to do it.
(control_bus_disconnected): Rename to control_disconnected
(control_disconnected): Work for system bus and private connections,
remove from the connections list.
* init/control.h: Add prototypes, remove global definition of bus
name to just being private again.
* init/tests/test_control.c (test_server_open, test_server_close)
(test_server_connect): Test the new functions.
(test_bus_open): add check for list entry
(test_bus_disconnected): rename to test_disconnected
* init/main.c: Open the listening server, warning if we're unable
to do so (but we won't treat it as a hard error since there's the
d-bus daemon as the default anyway).
* init/init.supp: suppress the fact that the control connections
list stays around.
* init/job_process.c (job_process_run): Use NIH_ZERO instead of
NIH_MUST and == 0
2008-05-06 Scott James Remnant <scott@netsplit.com>
* init/environ.c (environ_expand_until): Odd gcc optimiser warning,
it reckons arg_start and end may be used uninitialised, but I don't
see how they can be.
* init/main.c (main): Warn if we can't set the root directory.
* init/job_process.c (job_process_spawn)
(job_process_error_abort): loop on the return of write()
* init/tests/test_job_process.c (child, main): assert getcwd() works
(test_handler): initialise list and entry for gcc's blind spot.
(test_run): initialise ret for gcc's blind spot
* init/tests/test_job.c (test_name): jump through hoops for gcc
(test_change_state): list and entry.
* init/tests/test_event.c (test_finished_handle_jobs, test_finished)
(test_pending_handle_jobs, test_poll, test_pending): initialise to
NULL and buy gcc glasses
* init/tests/test_event_operator.c (test_operator_collect): another
NULL to make gcc happy.
2008-05-01 Scott James Remnant <scott@netsplit.com>
* TODO: Update.
* init/init.supp: Suppress a few test case artefacts caused by
valgrind hating reachable memory at exec() time.
* init/tests/test_job_process.c: Fix a few cases where we were
still dup'ing the name argument to job_new().
* init/tests/test_parse_job.c: Include missing signal.h
* init/event.c (event_pending_handle_jobs)
(event_finished_handle_jobs): Land the old job event handling
functions here as static functions, right now they're immense but
we'll actually move much of the code back out again as we go.
* init/tests/test_event.c (test_pending_handle_jobs)
(test_finished_handle_jobs): Also land the test cases in renamed
and somewhat restructued functions, since we now have to do the
testing through event_poll().
(test_poll, test_pending, test_finished): It never hurts to improve
test cases while you're in there.
2008-04-30 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_change_state): Change calls to job_process_run
and job_process_kill.
* init/main.c: Change to job_process_handler
* init/job_process.c, init/job_process.h: Land the code from job.c
and defs from job.h that deal specifically with a job's processes,
rename the functions to job_process_*() in the process.
* init/tests/test_job_process.c: And land the test cases as well.
* init/job.c: Strip of everything not related to creation and finding
of instances and the core state machine; process stuff will move to
job_process.c and event handling to event.c, class (nee config) stuff
is already moved to job_class.c
(job_new): Don't reparent the name, it doesn't help anything, just
take a copy.
(job_name, job_failed, job_unblock, job_emit_event): Make extern since
we need to use these outside or just want to test them.
* init/job.h: Clean out also.
* init/tests/test_job.c: Also clean out.
(test_name, test_failed, test_unblock, test_emit_event): Add test cases
for newly extern functions.
* init/main.c: Include events.h to get the ones we need.
* init/control.c (control_job_config_path, control_job_path)
(control_path_append): Drop these functions (replaced by the more
generic nih_dbus_path() function)
* init/control.h: Make CONTROL_ROOT public, and drop other prototypes.
* init/tests/test_control.c (test_job_config_path)
(test_job_path): Drop tests.
2008-04-29 Scott James Remnant <scott@netsplit.com>
* init/event.c, init/event.h, init/tests/test_event.c: Strip out the
event operator code and events list.
* init/job_class.c, init/job_class.h: We only need the event operator
code here now.
* init/events.h, init/event_operator.c, init/event_operator.h,
init/tests/test_event_operator.c: Separate out the event operator
code and the list of events into separate source files.
* init/Makefile.am (init_SOURCES): Build and link event operator code
and use the lists of events.
(TESTS): Build and run the event operator test suite.
(test_event_operator_SOURCES, test_event_operator_LDFLAGS)
(test_event_operator_LDADD): Details for the event operator test
suite.
(test_process_LDADD, test_job_class_LDADD)
(test_job_process_LDADD, test_job_LDADD, test_event_LDADD)
(test_parse_job_LDADD, test_parse_conf_LDADD, test_conf_LDADD)
(test_control_LDADD): Link the event operator code.
* init/job_class.c, init/main.c: Correct includes and some function
names.
* init/process.c, init/process.h, init/tests/test_process.c: Land
original Process code (used by job class and similar).
* init/process.c, init/process.h, init/tests/test_process.c: Break
into two pieces, one part becomes job_process which requires both
job information and process information, the other becomes system
which requires no job information.
* init/errors.h: Update error name.
* init/Makefile.am (init_SOURCES): Build and link job process code
and header along with system code and header.
(TESTS): Build and run job process and system test suites.
(test_job_process_SOURCES, test_job_process_LDFLAGS)
(test_job_process_LDADD): Details for job process test suite.
(test_system_SOURCES, test_system_LDFLAGS, test_system_LDADD):
Details for system test suite.
(test_process_LDADD, test_job_class_LDADD, test_job_LDADD)
(test_event_LDADD, test_parse_job_LDADD, test_parse_conf_LDADD)
(test_conf_LDADD, test_control_LDADD): Link job process and system
code.
* init/parse_conf.c: Remove parse_job include.
* init/init.supp: Update leak check for class init; remove
valgrind workaround since it's gone away with the change of that
function.
* init/conf.h (ConfFile): Change type of job member, but leave name.
Add prototype for new function.
* init/conf.c (conf_reload_path): Somewhat simplify the case of
having parsed a job, we only need to call job_class_consider() now
to have it dealt with.
(conf_file_destroy): Likewise after removing the ConfFile from the
source (so it won't get considered) and marking the job class as
deleted, we only need to call job_class_reconsider() and check the
return value to see whether we've been replaced.
(conf_select_job): In return we provide the function to decide which
of the available job sources is the best one.
* init/tests/test_conf.c: Update types in tests.
(test_select_job): Test the new function.
* init/parse_job.h: Update to include job_class.h and update prototype
to return JobClass, we'll keep the name though since we'll never
parse jobs and otherwise things get annoying.
* init/parse_job.c: Update to work on job classes.
* init/tests/test_parse_job.c: Update to match.
* init/job_class.h (JobClass): Factor out old JobConfig object into
a new JobClass object with the same properties, but in its own source
file.
(ExpectType): Rename old JobExpect to this to match other enums.
(ConsoleType): Move along with the object that uses it.
* init/job_class.c (job_class_init, job_class_new)
(job_class_environment): Bring along methods that only operate on
a JobClass, cleaning them up in the process.
(job_class_consider, job_class_reconsider): Replace job_config_replace
with these two functions that may be used for a new job class and
when discarding or finishing with an old one respectively.
* init/tests/test_job_class.c: Tests for the functions.
* init/Makefile.am (init_SOURCES): Build and link job class source
and header.
(TESTS): Build and run job class test suite.
(test_job_class_SOURCES, test_job_class_LDFLAGS)
(test_job_class_LDADD): Details for job class test suite.
(test_process_LDADD, test_job_LDADD, test_event_LDADD)
(test_parse_job_LDADD, test_parse_conf_LDADD, test_conf_LDADD)
(test_control_LDADD): Link job class code to other tests too.
2008-04-28 Scott James Remnant <scott@netsplit.com>
* init/control.c (control_job_config_path, control_job_path): Add
functions to generate D-Bus object paths for jobs and instances
(control_path_append): and a static function used by both to append
escaped path elements.
* init/control.h: Add prototypes.
* init/tests/test_control.c (test_job_config_path)
(test_job_path): Add test cases for the new functions.
* init/job.h (JobConfig, Job): Add path member to both structures.
* init/job.c (job_config_new, job_new): Initialise the path members.
* init/tests/test_job.c (test_config_new, test_new): Make sure
the path members are initialised to something sensible.
* init/init.supp: Valgrind whines, I do not know why.
* init/control.c (control_bus_open): Call out to register objects
on the new bus connection.
(control_register_all): Start off by registering the connection
manager object, no methods/signals for now.
* init/tests/test_control.c (test_bus_open): Make sure the manager
object is registered.
2008-04-27 Scott James Remnant <scott@netsplit.com>
* init/tests/test_control.c (test_bus_open): Correct name of
error macro.
* init/job.c (job_emit_event): Make INSTANCE the second variable.
* init/tests/test_job.c (test_next_state): Update tests.
2008-04-25 Scott James Remnant <scott@netsplit.com>
* init/tests/test_control.c (test_bus_open): Use D-bus macros for
error strings instead of naming them by hand.
2008-04-22 Scott James Remnant <scott@netsplit.com>
* init/tests/test_control.c (test_bus_close): Add another missing
call to dbus_shutdown.
2008-04-21 Scott James Remnant <scott@netsplit.com>
* init/tests/test_control.c (test_bus_open): Under valgrind we seem
to get NoReply instead of Disconnected which is a wee bit odd.
Add missing call
(test_bus_disconnected): Add missing call to dbus_shutdown.
2008-04-19 Scott James Remnant <scott@netsplit.com>
* init/process.c: Add missing limits.h include
* init/job.h (JobConfig): Merge instance and instance_name; if
instance is set, the job is multi-instance with the name derived
from that; if unset the job is singleton. We will not support
unlimited instances.
* init/job.c (job_config_new): Initialise instance to NULL.
(job_new): Assert that name is set for instance jobs.
(job_instance): Alter to only deal with singleton and instance
jobs, the unlimited instances case is gone.
(job_handle_event): Use instance instead of instance_name
* init/tests/test_job.c (test_config_new): Check instance is NULL
(test_find_by_pid): Adjust the way instance jobs are made, which
means we have to pass a name to job_config_new now.
(test_instance): Adjust tests to remove unlmited-instance tests
and pass name to job_config_new
(test_change_state, test_run_process): Pass instance name to
job_new as an allocated argument rather than waiting to set it
until afterwards.
(test_handle_event): Set instance instead of instance_name
* init/parse_job.c (stanza_instance): Make the argument mandatory.
* init/tests/test_parse_job.c (test_stanza_instance): Remove the
checks for without argument, and make sure that without argument
is an error.
* init/parse_job.c (stanza_oom): Oops, forgot to free never arg.
* init/job.h (JobConfig): NihList is rather overkill for emits,
which is static configuration; turn into a NULL-terminated array
which'll make it easier to turn into a D-Bus property later.
* init/job.c (job_config_new): Initialise to NULL now.
* init/tests/test_job.c (test_config_new): Make sure it's NULL.
* init/parse_job.c (stanza_emits): Store in an array instead.
* init/tests/test_parse_job.c (test_stanza_emits): Redo tests.
* init/job.c (job_emit_event): Append exported variables to the
job event without overwriting the builtins.
* init/tests/test_job.c (test_change_state): Check that exported
environment is added to the job events.
* init/parse_job.c (stanza_export): Parse a new export stanza,
which takes one or more environment variable names.
* init/tests/test_parse_job.c (test_stanza_export): Test the new
stanza.
* init/job.h (JobConfig): Add new export member.
* init/job.c (job_config_new): Initialise to NULL.
* init/tests/test_job.c (test_config_new): Make sure it's NULL.
* init/environ.c (environ_add, environ_set): Add a replace argument
which when FALSE does not replace existing entries in the environment
table.
* init/environ.h: Adjust prototypes.
* init/tests/test_environ.c (test_add): Add tests for non-replacement
mode, including corner cases.
(test_set): Replace should be TRUE in this test.
* init/event.c (event_operator_collect): Always replace existing
environment members.
* init/job.c (job_config_environment, job_run_process): Always replace
existing environment members.
(job_emit_event): Always replace existing environment members, and
rework this function to get rid of the confusing gotos.
* init/tests/test_job.c (test_change_state): Add tests to make sure
we include the INSTANCE variable in the event environment.
2008-04-18 Scott James Remnant <scott@netsplit.com>
* init/process.c (process_kill): Make sure we do send the signal to
the process group; in practice this makes no difference, but it pays
to be explicit in such things.
* init/tests/test_process.c (test_kill): Add a test case for when
the session leader is no more.
* init/job.h (JobConfig): Another day, another obscure job config
detail. This one is for adjusting how likely you are to be killed
by the OOM Killer.
* init/job.c (job_config_new): Set to zero by default.
* init/tests/test_job.c (test_config_new): And make sure it is zero.
* init/parse_job.c (stanza_oom): And it helps to have a function
to set that one.
* init/tests/test_parse_job.c (test_stanza_oom): Test it.
* init/errors.h: And we need an error if its out of bounds.
* init/conf.c (conf_reload_path): Which also needs to be caught.
* init/process.c (process_spawn): Of course, we have to do something
with the oom adjustment.
(process_error_read): message for failure error.
* init/process.h (processErrorType): And need an error if it fails
* init/main.c: Drop the legacy configuration directory, the format
of jobs has changed sufficiently to not support it.
* init/Makefile.am (AM_CPPFLAGS): Remove LEGACY_CONFDIR definition.
(install-data-local): Don't create it, either.
* init/enum.c, init/enum.h, init/tests/test_enum.c: Remove these
source files, a hold-over from when we had them in a separate
library and passed around the integer values.
* init/job.c, init/job.h, init/tests/test_job.c: Restore in their
proper place.
* init/Makefile.am: Remove enum.* from build instructions.
* init/main.c: Attempt to connect to the system bus on startup,
but don't expect it to work.
* init/control.c (control_bus_open, control_bus_disconnected)
(control_bus_close): Functions to open a connection to the D-Bus
system bus, clean up if disconnected or disconnect ourselves
explicitly.
* init/control.h: Prototypes.
* init/tests/test_control.c (test_bus_open)
(test_bus_disconnected, test_bus_close): Test the functions using
a fake D-Bus system bus daemon.
* init/errors.h: Add error for "name taken".
* init/Makefile.am (init_SOURCES): Build and link control.c and
control.h
(TESTS): Build and run control test suite.
(test_control_SOURCES, test_control_LDFLAGS, test_control_LDADD):
Details for control test suite.
(test_process_LDADD, test_job_LDADD, test_event_LDADD)
(test_parse_job_LDADD, test_parse_conf_LDADD, test_conf_LDADD):
Link control.o
2008-04-16 Scott James Remnant <scott@netsplit.com>
* init/job.h (JobConfig): Add leader member.
* init/job.c (job_config_new): Initialise leader to FALSE.
* init/tests/test_job.c (test_config_new): Make sure leader is FALSE.
(test_change_goal, test_change_state, test_run_process)
(test_kill_process, test_child_handler, test_handle_event)
(test_handle_event_finished): Jobs have to be leaders now to allow
waitpid() to work in test cases.
* init/parse_job.c (stanza_session): Parse "session leader" stanza
to set to TRUE.
* init/tests/test_parse_job.c (test_stanza_session): Test new
stanza parsing.
(test_stanza_console): Add missing "missing argument" test.
* init/process.c (process_error_read): Deal with new fork error.
(process_spawn): If we're not to be a session leader, fork again and
write the pid back on the open socket.
* init/process.h (ProcessErrorType): Introduce new fork error.
* init/tests/test_process.c (test_spawn): Test that we can't start
a non-session-leader and still have process details.
(test_spawn, test_kill): Other jobs have to be leaders now to
allow waitpid() to work.
* init/tests/test_event.c (test_poll): Jobs have to be leaders now
to allow waitpid() to work.
2008-04-12 Scott James Remnant <scott@netsplit.com>
* configure.ac (NIH_INIT): Require that libnih build D-Bus support,
failing configure if we can't get it.
* init/Makefile.am (AM_CFLAGS): Build with D-Bus CFLAGS,
(init_LDADD, test_process_LDADD, test_job_LDADD, test_event_LDADD)
(test_parse_job_LDADD, test_parse_conf_LDADD, test_conf_LDADD): and
link with libnih-dbus.la and D-Bus LIBS.
(init_LDFLAGS): No need for -static now since libnih will only exist
statically anyway.
* init/main.c: Use a better name for kbdrequest
* init/event.h (KBDREQUEST_EVENT): Rename event to keyboard-request
* init/main.c: Drop the attempt to rescue a crashed system by
carrying on with no state
(crash_handler): After the child has core dumped, the parent will
die and the kernel will panic. That's the best we can do, I think.
* init/job.c (job_change_state): Don't generate the stalled event;
there's nothing useful you can do with it other than start a root
shell and that's just a security hole waiting to happen.
(job_new): Don't increment the instances counter.
* init/job.h: Remove extern for instances counter.
* init/tests/test_job.c (test_new): Remove the check that the
instance counter is incremented.
(test_change_state): Remove the test for the stalled event.
* init/event.h (STALLED): Remove stalled event definition,
* TODO: Update.
* init/job.h (Job): And while we're at it, the instance name is
guaranteed unique for a given job name, which is also guaranteed
to be unique - so don't bother with job ids either, since they
also get reused in bad cases.
* init/job.c (job_next_id): Drop this function.
(job_new): Don't assign an id anymore.
(job_find_by_id): Drop this function.
(job_run_process): Set UPSTART_INSTANCE to the instance name if set.
(job_name): Function to create the string used in messages.
(job_change_goal, job_change_state, job_run_process)
(job_kill_process, job_kill_timer, job_child_handler)
(job_process_terminated, job_process_trace_new)
(job_process_trace_new_child, job_process_trace_signal)
(job_process_trace_fork, job_process_trace_exec): Use the instance
name in messages (if set) in place of the job id.
* init/tests/test_job.c (test_new): Drop checks on the id field.
(test_find_by_id): Drop test.
(test_run_process): Check that UPSTART_INSTANCE is set only for
named job instances, and contains the instance name.
(test_change_state, test_run_process, test_child_handler): Remove
id setting and update error message checks.
* TODO: Update.
* init/event.h (Event): We don't use the id field for anything;
and it can't be guaranteed to be unique since it can wrap over
and get reused. Drop it.
* init/event.c (event_next_id): Drop this function.
(event_new): Don't assign an id anymore.
(event_find_by_id): Drop this function.
* init/tests/test_event.c (test_new): Drop checks on the id field
(test_find_by_id): Drop test.
(test_poll): Drop id setting which was needless anyway.
2008-04-11 Scott James Remnant <scott@netsplit.com>
* init/tests/test_job.c (test_child_handler): Add tests to make
sure that respawn works for both services and tasks; the only
difference we want for tasks is that zero is a normal exit code.
* init/job.c (job_process_terminated): Status need not be non-zero
if the job is not a task.
Change the default job type from task to service, which will
finally match people's expectations.
* init/job.h (JobConfig): Replace service member with task
* init/job.c (job_config_new): Initialise task to FALSE
(job_change_state): Unblock if not a task instead of if a service
* init/tests/test_job.c (test_config_new): Make sure task is FALSE
(test_change_state): Check service by default, task with flag;
this also means we expect blockers to be cleared if we end up in
running for the other checks
(test_child_handler): Expect blockers to be cleared if we end up
in running now that service is the default.
* init/tests/test_event.c (test_poll): Test with a task since
we want to remain blocked for longer.
* init/parse_job.c (stanza_respawn): Don't set service to TRUE
(stanza_service): Rename to stanza_task and set task flag instead
* init/tests/test_parse_job.c (test_stanza_respawn): Remove checks
for setting of service flag
(test_stanza_service): Rename to test_stanza_task and test task
* init/job.c (job_init): Create hash using nih_hash_string_new()
* init/conf.c (conf_source_new): Likewise.
2008-03-08 Scott James Remnant <scott@netsplit.com>
* HACKING: Terminology changes: Bazaar-NG is now just Bazaar;
Malone is now just Launchpad's bug tracking system. Update bugs
URL to match modern form.
* init/enum.h (JobWaitType): Rename to JobExpect
* init/job.h (JobConfig): Rename wait_for to expect
* init/job.c (job_config_new, job_change_state, job_run_process)
(job_process_stopped, job_process_trace_new_child): Rename wait_for
to expect in all occurances.
* init/tests/test_job.c: Likewise rename all occurances.
* init/parse_job.c (stanza_wait): Rename to stanza_expect and drop
the intermediate argument.
* init/tests/test_parse_job.c (test_stanza_wait): Rename to
test_stanza_expect and adjust tests to match new syntax.
* init/tests/test_process.c (test_spawn): Remove set of wait_for.
* doc/states.dot: Remove the state transition from starting to
waiting ("emit_stopped" in the graph); we don't have a "respawning
too fast" exit here anymore, so always go to stopping.
* doc/states.png: Regenerate.
* TODO: Document the problems with overflowing ids and instance
counter before I forget about them.
2008-03-07 Scott James Remnant <scott@netsplit.com>
* TODO: Update.
* init/job.h (JobConfig): Add instance_name member.
(Job): Add name member.
* init/job.c (job_config_new): Initialise instance name to NULL.
(job_new): Accept the name as an argument, reparenting and stealing
(job_handle_event): Expand the instance name and pass to job_new
(job_instance): Accept a name and look that up in the list of current
instances returning the instance if found.
* init/tests/test_job.c: Add extra argument to all job_new calls
(test_config_new): Make sure instance name is initialised to NULL.
(test_handle_event): Make sure the job name is set from the instance,
and make sure an existing instance is reused if we can.
(test_instance): Make sure that the existing instance is returned.
* init/parse_job.c (stanza_instance): Check for an optional argument
and store it in the instance_name member if it exists, otherwise
free and reset the instance_name member.
* init/tests/test_parse_job.c (test_stanza_instance): Check the new
argument is handled properly and stored in the right place.
* init/tests/test_conf.c (test_source_reload_job_dir)
(test_file_destroy): Add extra NULL to job_new
* init/tests/test_event.c (test_poll): Add extra NULL to job_new
* init/event.c (event_operator_match): Accept an environment array
and expand the operator value against it before attempting to match.
(event_operator_handle): Also accept the environment array and pass
through to calls to event_operator_match().
* init/event.h: Update prototypes.
* init/tests/test_event.c (test_operator_match): Add extra NULL
argument to most tests, and add tests for known and unknown variable
references.
(test_operator_handle): Add extra NULL arguments to most tests, and
add test for passing of environment through.
(test_operator_reset): Add extra NULL argument to call.
* init/job.c (job_handle_event): Pass the job environment for the
stop event handling, but NULL for the start event.
* init/tests/test_job.c (test_handle_event): Make sure that a stop
operator is expanded from the job environment before being matched
against the stop event.
* init/event.c, init/event.h, init/environ.c: Documentation tweaks.
* init/job.c (job_change_state): Remove the code to check for runaway
jobs from here, we'll always let people explicitly start an instance.
(job_process_terminated): Call job_catch_runaway when actually doing
the respawn instead.
* init/tests/test_job.c (test_change_state): Remove "too fast" checks,
we're going to allow start/stop requests to restart jobs as much as
they like since this is an external request.
(test_handle_event, test_handle_event_finished): No need to remove
a respawn limit with this behaviour.
(test_child_handler): Instead check that the respawn counter is
dealt with by the child handler.
* TODO: Update, I found a bug with the current model.
* init/tests/test_environ.c (test_expand): Check that a string
without an expansion still works ok.
2008-03-06 Scott James Remnant <scott@netsplit.com>
* init/event.c (event_operator_collect): Just use strcat functions.
2008-03-03 Scott James Remnant <scott@netsplit.com>
* init/environ.c (environ_valid): New function to check the validity
of an environment variable name, should call before accepting any.
(environ_expand_until): New function to expand variable references
in a string using an environment table; supports a few common
shell-like expressions.
(environ_getn): Change to return the value of the string, not the
entire environment string.
* init/environ.h: Add prototypes.
* init/errors.h: Add errors raised by new functions.
* init/tests/test_environ.c (test_valid, test_expand): Add test
cases for the new functions.
(test_get, test_getn): Change test case to check for the variable
value instead of returning the whole string.
* TODO: Add thoughts on blocking commands.
* TODO: Update.
* init/event.h (Event): Remove the refs member; we now never hold
a reference to an event we're blocking since we always copy the
environment out if we want to keep it.
(EventOperator): Events are always blocked while we hold them,
so drop the blocked member.
(EventProgress): The done state is no longer needed, we can free
in finished now.
* init/event.c (event_ref, event_unref): Drop these functions.
(event_new): Don't ininitialise the refs member since it's gone.
(event_poll): Remove the done state since it's directly freed
in event_finished again
(event_finished): No done state, event is freed before return.
(event_operator_new): No blocked member.
(event_operator_copy): Always block the event after copying.
(event_operator_destroy): Simply unblock.
(event_operator_handle): Simply block the event on match.
(event_operator_collect): Always block the copied event
(event_operator_unblock): This function is no longer required, since
it has an identical effect to reset.
(event_operator_reset): Simply unblock the event.
* init/tests/test_event.c (test_new): Drop the check for refs
being initialised to zero.
(test_ref, test_unref, test_operator_collect): Drop test for
functions that have been dropped in the code.
(test_operator_new): Drop the check for blocked being initialised
to FALSE.
(test_block, test_unblock, test_operator_destroy): Drop any references
to the refs member.
(test_operator_destroy): Actually fix the function to test things.
(test_poll): Drop the check for remaining in the done state.
(test_operator_new, test_operator_copy): Drop the checks for blocked.
(test_operator_handle, test_operator_collect, test_opreator_reset):
Drop references to refs and blocked.
* init/job.c (job_unblock, job_handle_event): Drop the call to
event_unref() since the next call was always event_unblock() and
that's the one that we didn't delete.
* init/tests/test_job.c (test_change_state, test_child_handler)
(test_handle_event, test_handle_event_finished): Events don't
have references anymore, so remove calls to reference, unreference
and checks for the reference count - it's all done with blocks now.
(test_new): Remove check that the operator is not blocked for a
new job since there's no such thing now.
(test_handle_event): Operators don't have a blocked member anymore,
if there's an event, it's blocked.
* init/job.c (job_change_state): Don't reference the event we're
blocked on, we'll always know when it's finished.
(job_handle_event_finished): Likewise no reason to unreference it.
* init/tests/test_job.c (test_change_goal, test_child_handler)
(test_handle_event, test_change_state)
(test_handle_event_finished): Remove the expectation that the blocked
event is referenced by the job.
* init/tests/test_event.c (test_poll): Don't reference the event,
since the job would not have.
* init/job.c (job_emit_event): Use environ_add/set for style
reasons.
* init/job.c (job_handle_event): Reset the stop_on operator after
processing the event, thus the expression needs to be completely
reevaluated before the job can be stopped again by it. At last,
correct behaviour!
(job_change_state): No reason to reset the stop_on operator when
starting since it's always reset after evaluating to TRUE now;
likewise no reason to reset on re-entering running or waiting,
job_unblock() is sufficient.
(job_failed): No reason to iterate stop_on to set failed, it's
empty - job_unblock() does what we want.
* init/tests/test_job.c (test_handle_event): Check that the operator
is actually reset and the event not referenced when handling from
the event.
(test_change_state, test_child_handler): Don't put anything in stop_on
and thus don't expect anything to come out of it -- event environment
is all done in stop_env and blocking done in blocking.
* init/job.c (job_handle_event): Collect the stop events and store
them in the blocking list, unblocking any that were there before
such as the start events.
(job_change_state): Unblock blocking events when returning to running
from pre-stop.
* init/tests/test_job.c (test_handle_event): Make sure the stop
events are collected and replace any previously blocking events.
(test_change_state, test_child_handler): Test that stop events in
the blocking list are kept and unblocked when necessary.
2008-03-02 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_change_state): Shouldn't emit the started event
on pre-stop cancellation, and shouldn't unblock the job because
it's a service.
* init/job.c (job_change_state): Throw away the stop environment
when starting and returning to running.
* init/tests/test_job.c (test_change_state): Make sure the stop
environment is actually thrown away.
* init/job.c (job_run_process): Append the environment from the
stop events if given the pre-stop process to run; do this before
the special events so they can never be overriden.
* init/tests/test_job.c (test_run_process): Check that the stop event
environment is included for pre-stop and not for other jobs.
* init/job.c (job_handle_event): Remove setting of UPSTART_JOB
and UPSTART_JOB_ID, we set that when we run the process.
* init/tests/test_job.c (test_handle_event): Don't check for
UPSTART_JOB and UPSTART_JOB_ID since we no longer copy it in here.
* init/job.c (job_run_process): Copy the environment to pass it to
the job, appending the UPSTART_JOB and UPSTART_JOB_ID variables here;
we never want to be able to match these, etc.
* init/tests/test_job.c (test_run_process): Add tests to make sure
that the environment is actually set in the processes we run.
* init/job.h (Job): Add stop_env member to store environment from
stop events for the stop script.
* init/job.c (job_new): Initialise stop_env to NULL.
(job_handle_event): Copy environment from the stop_on operator into
the stop_env member.
* init/tests/test_job.c (test_new): Check that stop_env is NULL.
(test_handle_event): Add lots of tests to make sure that the
environment is collected from the events and stored in stop_env
properly, overwriting what was there already if necessary.
* init/init.supp (job-run-process-args): Add a suppression for the
fact that job_run_process will leak its arguments to a new process
assuming that it will call exec() or exit()
* init/tests/test_job.c (test_child_handler): Remove bogus free tag
of the list, which we don't use in this test (valgrind failure)
* init/job.h (Job): Remove the start_on member.
* init/job.c (job_new): Don't initialise start_on since it's gone.
(job_change_state): Drop call to unblock the start_on operator since
the events are already unblocked by job_unblock.
(job_failed): Drop setting of start_on events to failed since this
is already done by job_unblock. This results in a slight change in
behaviour, now when a job fails to start - the event or command will
be immediately unblocked since there's no point waiting until it
stops again - it was waiting for it to start.
* init/tests/test_job.c (test_new): Remove start_on checks
(test_change_state, test_child_handler, test_handle_event): Remove
all references to start_on, instead relying on the blocking checks
instead.
* init/tests/test_event.c (test_poll): Remove solitary reference
to job's start_on, this wasn't necessary anyway - we proved that it
was the right event by affecting the job. Revert previous commit
that temporarily increased the number of references, they should be
one again now only the blocking list holds them.
* init/job.h (job): Add blocking member, a list of events that we're
blocking from finishing.
* init/job.c (job_new): Initialise blocking member to NULL.
(job_handle_event): Collect the list of events from the operator
and store them in the job's blocking list (unblocking any existing
first); if the job is already running, unblock unref and discard.
(job_unblock): New function to deal with unblocking the events we're
holding onto and resetting the blocking list; this will be extended
later to also unblock any command.
(job_change_state): Unblock events in running for services and in
waiting for everything.
(job_failed): Unblock events and mark them as failed.
* init/tests/test_job.c (test_new): Check that it's initialised to NULL
(test_handle_event): Extend the test cases to check the value of the
blocking list, and to make sure that the previous blocking list is
overwritten when necessary.
(test_change_state, test_child_handler): Extend test cases so that
wherever we're had a blocked event in start_on, we also have that in
the blocking list.
* init/tests/test_event.c (test_poll): Temporarily increase the
expected number of references/blockers to the event in the poll
test.
* init/job.h (Job): Add start_env member, this stores the environment
to use when starting the event so it doesn't overwrite the current
environment of a restarting job.
* init/job.c (job_handle_event): Do the heavy lifting of starting a
new job instance here; construct the environment from the built-ins
and configured, append that collected from the start events, locate
or create a new instance, add the job name and id then copy into
the new start_env member before starting the job. At some point
this will probably all become a function since it'll be similar for
the control functions.
(job_change_state): Copy the start_env member into the env member
when in the starting state; thus the job environment remains the same
until restarted.
(job_new): Remove code to initialise the environment, we now do that
when actually starting the instance.
* init/tests/test_job.c (test_handle_event): Add test cases for
starting the job, making sure that the environment is correctly
copied into the right field and also checking what happens if it's
already stopping or running.
(test_change_state): Make sure that start_env is correctly copied
over into env, overwriting what is there if non-NULL or keeping it
if NULL.
(test_new): Remove checks for environment setup, since we don't do
that anymore here; replace with checking for NULL and restore the
alloc fail tests.
* TODO: Update.
* init/environ.c (environ_add): Allow it to accept NULL length, since
we can't always keep that around.
* init/process.c (process_spawn): Accept the environment list as
a parameter, then finally we can change this function to take a
JobConfig as the first argument.
(process_error_read): Remove the associated error handler.
* init/process.h: Change prototype.
(ProcessErrorType): Remove error enum for environment.
* init/tests/test_process.c (test_spawn): Update calls in test to
just pass in an environment array (direct testing).
* init/job.c (job_run_process): Pass configuration and environment
to process_spawn.
* init/process.c (process_spawn): Take the environment directly out
the job structure, rather than recreating it.
(process_environment): Drop function, absorbed elsewhere.
* init/process.h: Remove prototype.
* init/tests/test_process.c (test_spawn): Set the job_id variable
before calling job_new and set config->start_on instead of
job->start_on so that job_new can pick up both.
(test_environment): Remove test cases.
* init/job.h (Job): finally gains env pointer of its own.
* init/job.c (job_new): Initialise the environment, moving the last
of the code from process_environment -- this is only temporary
though in the interests of refactoring, it'll move out of here again
soon enough.
* init/tests/test_job.c (test_new): Make sure that the environment is
set in a manner which tests the overriding of things by other things;
we have to temporarily comment out the alloc fail stuff though :-(
* init/event.c (event_operator_collect): Make list the last argument
for consistency with future functions.
* init/event.h: Update prototype.
* init/tests/test_event.c (test_operator_collect): Swap arguments.
* init/process.c (process_environment): Update.
* init/job.c (job_config_environment): Function to generate an
environment table from a JobConfig, code largely moved from process.c
* init/job.h: Add protoyype.
(JOB_DEFAULT_ENVIRONMENT): List of environment variables to always
copy from the environment (moved from process.h)
* init/tests/test_job.c (test_config_environment): Add test case,
again largely copied from test_process.c
* init/process.c (process_environment): Call job_config_environment
instead of the code moved out.
* init/process.h (PROCESS_ENVIRONMENT): Move to job.h
* TODO: Update.
* TODO: Update.
2008-03-01 Scott James Remnant <scott@netsplit.com>
* init/event.c (event_operator_collect): Create a mega-function to
iterate an EventOperator tree (filtering out those bits that aren't
TRUE) and collect the events, adding them to a linked list, adding
their environment to a table and making a string list for another
environment variable. Fundamentally this function marshals data
out of the Event subsystem into the right format for the Job subsystem.
* init/event.h: Add prototype.
* init/tests/test_event.c (test_operator_collect): Tests for the
collector function; some bits may seem similar to test_process.c
* init/process.c (process_environment): Use event_operator_collect
to gather the environment, instead of its own code (which pretty
much got pasted into event_operator_collect anyway). Force everything
else to allocate matching the caller.
* init/tests/test_process.c (test_spawn, test_environment): Had
forgotten to set the value of the intermediate AND operator to TRUE,
necessary now.
* init/process.c (process_environment_add): Move and rename this
function, since it's not really process associated
(process_environment): Change to use environ_add or environ_setf
instead.
* init/process.h: Remove prototype.
* init/environ.c (environ_add): New name/location of
process_environment_add, modified to not take a copy of the string
(environ_set): Wrapper for the above for common dealing with
environment we want to set from a format string.
(environ_get, environ_getn, environ_lookup): Functions to get an
environment variable entry; largely cripped from event.c but
bug-fixed at the same time.
* init/environ.h: Function prototypes.
* init/event.c (event_operator_match): Change to use environ_lookup
* init/tests/test_process.c (test_environment_add): Move the tests.
* init/tests/test_environ.c: Test suite for environment handling
* init/Makefile.am (init_SOURCES): Build environ.c and environ.h
(TESTS): Build environment test suite
(test_environ_SOURCES, test_environ_LDFLAGS, test_environ_LDADD):
Details for environment test suite
(test_process_LDADD, test_job_LDADD, test_event_LDADD)
(test_parse_job_LDADD, test_parse_conf_LDADD, test_conf_LDADD):
Link environ.o to other test suites
* init/job.c (job_new): Increment the number of instances.
(job_instance): Simplify the function, it now only returns the
existing instance or NULL. This makes it easier to extend when
we have env-limited instances later on.
(job_handle_event): If job_instance returns NULL, create
a new instance with job_new() and always reset the operator afterwards.
* init/tests/test_job.c (test_new): Check that the instances variable
is incremented when a new job is created.
(test_instance): Change to check that it returns NULL when there is
no active instance, or for multi-instance jobs, instead of creating
a new one itself.
(test_config_replace, test_find_by_pid)
(test_find_by_id, test_change_goal, test_change_state)
(test_next_state, test_run_process, test_kill_process)
(test_child_handler, test_handle_event)
(test_handle_event_finished): Call job_new to create a new instance
from a config, instead of job_instance.
* init/tests/test_conf.c (test_source_reload_job_dir)
(test_file_destroy): Call job_new to create a new instance from a
config, instead of job_instance.
* init/tests/test_event.c (test_poll): Call job_new to create a new
instance from a config, instead of job_instance.
* init/tests/test_process.c (test_spawn, test_environment): Call
job_new to create a new instance from a config, instead of job_instance
2008-02-29 Scott James Remnant <scott@netsplit.com>
* configure.ac: Compare the evaluated $sbindir against the common
things we put in PATH, if it doesn't match, define EXTRA_PATH to
contain it.
* init/paths.h: Append EXTRA_PATH to PATH if defined.
* init/Makefile.am (AM_CPPFLAGS): Replace TELINIT definition with
SBINDIR, pointing at the common directory.
* compat/sysv/Makefile.am (AM_CPPFLAGS): Replace SHUTDOWN definition
with SBINDIR, pointing at the common directory.
* init/paths.h (TELINIT): Redefine to be SBINDIR with "/telinit"
on the end; define SBINDIR if necessary.
* compat/sysv/reboot.c (SHUTDOWN): Redefine to be SBINDIR with
"/shutdown" on the end; define SBINDIR if necessary.
2008-02-22 Scott James Remnant <scott@netsplit.com>
* init/event.c (event_operator_match): Rewrite to match both
positionally and by name.
* init/tests/test_event.c (test_operator_match): Update tests to
check the new behaviour works.
* init/parse_job.c (parse_on_operand): Add arguments to env list
rather than args; sanity check afterwards to ensure that positional
doesn't follow name-based -- when parsing the job is the right place
to catch this.
* init/tests/test_parse_job.c (test_stanza_start)
(test_stanza_stop): Change args to env when checking operators.
Check that arguments may be quoted in manners that we expect to be
sane. Check that positional arguments cannot follow name-based ones.
* init/errors.h: Add new error.
* init/conf.c (conf_reload_path): Treat expected variable as a
permanent error.
* init/tests/test_process.c (test_spawn, test_environment):
Update event_new() calls to remove extra argument.
* init/main.c (main, cad_handler, kbd_handler, pwr_handler):
Update event_new() calls to remove extra argument.
* init/job.c (job_change_state): Update event_new () call.
(job_emit_event): Update to put failure information in environment.
* init/tests/test_job.c (test_new, test_instance)
(test_child_handler, test_handle_event)
(test_handle_event_finished): Remove extra argument to event_new,
rename args to env in operator where necessary.
(test_change_state): Update to check emitted event by full environment.
* init/event.h (Event): Remove args member.
(EventOperator): Rename args member to env.
Update prototypes to match.
* init/event.c (event_new): Remove args member.
(event_finished): Remove copying of args member to failed event.
(event_operator_new): Rename args member to env.
(event_operator_copy): Rename args copying to env.
(event_operator_match): ??
* init/tests/test_event.c (test_new): Update test to remove args.
(test_operator_new): Update test to rename args to env.
(test_operator_copy): Update test to rename args to env.
(test_operator_match): ???
* TODO: Update with job atomicity notes.
2008-02-20 Scott James Remnant <scott@netsplit.com>
* init/job.c: Switch around job_find_by_pid and job_find_by_id
* init/job.h: Likewise.
* init/job.h: Update prototypes to match variable names in the
code.
2008-02-17 Scott James Remnant <scott@netsplit.com>
* init/process.c (process_kill): Change to accept a JobConfig rather
than a Job, since in theory this should only ever need that in a
future where we can specify a kill signal (right now it's not used
for anything!)
* init/process.h: Update prototype.
* init/tests/test_process.c (test_kill): Update test cases.
* init/job.c (job_kill_process, job_kill_timer): Pass in JobConfig
instead of Job.
* init/process.c (process_spawn): Accept trace as an argument instead
of using a random piece of job state to determine whether to trace
or not.
* init/process.h: Update prototype.
* init/tests/test_process.c (test_spawn): Update tests to pass in
via argument whether to trace the job or not.
* init/job.c (job_run_process): Pass in the trace variable rather
than relying on it working it out for itself; this means we don't
need to set the state until after, therefore don't need to reset it.
* AUTHORS, logd/jobs.d/logd.in: Update e-mail addresses.
* README: Update kernel recommendation to 2.6.24, since that's
the oldest version that the test suite will complete under.
2008-01-17 Scott James Remnant <scott@netsplit.com>
* TODO: Update.
* init/job.c (job_run_process): Don't append the list of event
names, they can be found in $UPSTART_EVENTS now. This is better
since it's consistent for exec and script.
* init/tests/test_job.c (test_run_process): Drop test case.
* init/process.c (process_environment): Function to build an
environment table for a job containing built-in variables, those
from the configuration, events and finally the upstart job ones.
(process_environment_add): Helper function for the above that
handles adding a variable to the array; dealing with fetching the
value from init's environment if necessary.
(process_setup_environment): This function now gets dropped in
favour of the new ones.
(process_spawn): Call the new process_environment() function and set
the environ variable directly.
* init/process.h (PROCESS_ENVIRONMENT): Define built-in environment
variables that are always copied from our own environment.
Add prototypes.
* init/tests/test_process.c (test_environment): Check that the
environment is built correctly and that each bit overrides the
right other bit.
(test_environment_add): Check that the array is built correctly.
(test_spawn): Adjust order and values of expected environment
to match what's now set.
2008-01-16 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_failed): Separate the logic that marks the job
and its associated events as failed into its own function, since
it's a large enough amount of code that we were otherwise duplicating
everywhere else (and in a few places, failing to mark the events as
failed as well).
(job_change_state, job_process_terminated): Call job_failed instead
of doing it ourselves.
(job_emit_event): De-nest the logic and fix so that we don't add
environment to the failed respawn event.
* init/tests/test_job.c (test_change_state): Add checks on whether
the event was marked as failed or not.
* TODO: Update.
* configure.ac (AC_COPYRIGHT): Update copyright to 2008.
* TODO: Update.
* init/tests/test_job.c (test_child_handler): Don't run the signal
and ptrace tests while in valgrind, sometimes signals (specifically
SIGCONT after SIGSTOP) don't behave right and we kinda need that
reliability.
* init/tests/test_job.c (test_child_handler): After adding extra
processes, make sure we clean up again so each test is roughly
independant. Fix the final test case to not rely on previous
setup and work on its own.
* init/tests/test_job.c (test_change_state): Remove useless check
of job->start_on from a killed/post-stop check (noticed while
writing the other).
* init/job.c (job_change_state): Check the return value of
job_run_process() and if particular processes fail, change the
goal to stop and push the job into the next state; setting the job
as failed along the way.
(job_emit_event): If the exit_status is -1 then it means the job
failed to spawn, so don't place EXIT_SIGNAL or EXIT_STATUS in the
event environment.
* init/tests/test_job.c (test_change_state): Check what happens when
each process type fails, make sure that the job is stopped for
pre-start, spawned and post-stop and the failure is ignored for
post-start and pre-stop.
2008-01-15 Scott James Remnant <scott@netsplit.com>
* init/main.c: Selectively compile out certain pieces when make is
run with CPPFLAGS=-DDEBUG, giving us a build that'll happily run from
a user terminal.
* init/event.h: Change the startup event to "debug" when built like
that, so we don't accidentally do bad things.
* init/job.c (job_run_process): Catch PROCESS_ERROR and abort the
attempt to run the process, returning a non-temporary error condition.
* init/tests/test_job.c (test_run_process): Add test case for
attempting to spawn a file that doesn't exist.
* init/process.c (process_error_read): Avoid the word process, since
it's likely included in the higher error message.
* init/process.c (process_spawn): Call process_error_abort() on any
error condition.
* init/tests/test_process.c (test_spawn): Add a test case for failing
to spawn a process and receiving ProcessError correctly; fix other
cases to ensure they return a pid.
* init/errors.h: Add PROCESS_ERROR to the enum, but not to the string
list since there's no specific defined string for this one.
* init/process.h (ProcessError): Structure that builds on NihError
to add additional information for a process error.
(ProcessErrorType): enum of different process error types.
* init/process.c (process_spawn): After forking read the error in
the parent, returning if we raise one.
Ensure we close the pipe if the fork fails.
Re-order so that we set the environment, umask and priority after the
resource limits (which should apply to them).
(process_error_abort): New function to immediately abort with an
error, writing it on the pipe first.
(process_error_read): Counterpart function to read the error from
the pipe and raise it, with appropriate error messages.
* init/process.c (process_spawn): Create a pipe to use for
communication with the child, ensuring its closed before the parent
returns and ensuring that the writing end is close-on-exec in the
child.
* init/job.c (job_run_process): Change to return a value indicating
whether there's been a non-temporary error (always returns zero so
far).
* init/job.h: Update prototype.
* init/tests/test_job.c (test_run_process): Check that job_run_process
always returns zero.
* init/job.c (job_change_goal): Document in which states this function
has unexpected side-effects such as freeing the job, since we do
attempt to call it from within job_change_state().
* init/process.c (process_setup_limits): Integrate this function back
into process_spawn() since there's no reason for it to be separate.
(process_setup_console): Alter this function so it closes the original
console descriptors, opens the new ones and can reset them to if
required -- in particular, this no longer takes a Job parameter.
(process_spawn): Use the new process_setup_console function and
integrate code from process_setup_limits().
* init/process.h: Update function prototype.
* init/main.c (main): Use the new process_setup_console() argument
form. Move syslog opening to the end of the function, rather than
where it is now where it could be at risk of being closed again
immediately. Change the root directory in case we're run in some
weird way.
(reset_console): Remove function since the code is now in
process_setup_console()
* init/enum.h (console_type): Remove CONSOLE_LOGGED and make the
CONSOLE_NONE constant be zero.
* init/parse_job.c (stanza_console): Drop parsing of "logged"
* init/tests/test_parse_job.c (test_stanza_console): Drop testing
of "logged" parsing.
2008-01-14 Scott James Remnant <scott@netsplit.com>
* HACKING: Correct bzr URLs to trunk.
2007-12-15 Scott James Remnant <scott@netsplit.com>
* init/process.c (process_spawn): Fix some documentation strings.
* init/process.c (process_kill): Move to beneath the process setup
functions.
* init/process.h: Adjust ordering here too.
* init/process.c (process_spawn): Group console closing and setup
together, becoming the session and process group leader first.
2007-12-07 Scott James Remnant <scott@netsplit.com>
* init/process.c (process_spawn): Drop the debug message since
it's always repeated by the caller.
* init/job.c (job_run_process): Drop the word Active which is a
hold-over from when we had different process states.
* TODO: Update.
* init/job.c (job_child_handler): Add code to handle the trapped
signal and ptrace event cases, distinguishing between a trapped
signal and process stopped after exec or fork using our trace
state member. Call out to other functions to do the work.
(job_process_trace_new): Called after the first exec to set the
ptrace options, update the trace state and allow the process to
continue without delivering the signal. Also called after the
fork to do the same.
(job_process_trace_new_child): Called after a fork for the new child;
increments the fork counter and if it goes over the number we want,
detaches from the process and allows it to move to running. Otherwise
calls job_process_trace_new() instead.
(job_process_trace_signal): Called when a signal is trapped, simply
delivers it to the process unchanged.
(job_process_trace_fork): Called before a fork for the parent, obtains
the new child process id from the event, updating the job structure,
and detaches from the parent which we're no longer interested in.
(job_process_trace_exec): Called after an exec other than the first,
assumed to be the end of forking so detaches from the process and
allows it to move to running.
* init/tests/test_job.c (test_child_handler): Add test cases for
the various ptrace states.
* init/job.c (job_run_process): Set process trace state to new for
the main job if we need to wait for the daemon or fork; otherwise
reset the state.
* init/tests/test_job.c (test_run_process): Add test cases to make
sure the trace state is set right and picked up by process_spawn.
* init/process.c (process_spawn): Set a ptrace before execing the
binary if the trace state is TRACE_NEW, set by the caller.
* init/tests/test_process.c (test_spawn): Make sure that a job is
ptraced if set up properly.
(child): Add a simple case that just exits immediately for testing
the above.
* init/job.h (Job): Add new trace_forks member to keep count of how
many forks we've seen and trace_state member to track whether we've
just started the trace or just forked.
* init/enum.h (TraceState): Add enumeration to keep track of ptrace
state to differentiate between a signal and an event.
* init/job.c (job_new): Initialise new members.
* init/tests/test_job.c (test_new): Check new members are initialised
* init/enum.h (JobWaitType): Add new daemon and fork wait types.
* init/parse_job.c (stanza_wait): Add parsing for daemon and fork.
* init/tests/test_parse_job.c (test_stanza_wait): Add tests too.
* init/job.h (JobConfig): Remove daemon and pid members.
(Job): Remove pid_timer member.
(JOB_DEFAULT_PID_TIMEOUT): Remove this constant.
* init/job.c (job_config_new, job_new): Remove initialisation of
removed members.
(job_change_state): Stay in spawned unless we're not waiting for
anything -- remove the daemon flag.
* init/tests/test_job.c (test_config_new, test_new): Remove checks
for initialisation of removed members.
(test_change_state): Remove daemon flag stays in spawned check since
the daemon flag has gone.
* init/parse_job.c (stanza_daemon, stanza_pid): Remove these
functions since they have no members to set.
* init/tests/test_parse_job.c (test_stanza_daemon, test_stanza_pid):
Remove the tests for the now non-existant functions.
* init/process.c (process_spawn): raise the system error before
calling another syscall, in case we overwrite errno.
2007-12-06 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_child_handler): Implement a combined child event
handler to replace the multiple separate ones. This handler deals
with adding appropriate messages to the log and decoding any state
information before calling specific action functions.
(job_child_reaper): Remove, moving the bulk of the code into new
(job_process_terminated): function that handles it cleanly.
(job_child_minder): Remove, moving the bulk of the code into new
(job_process_stopped): function that's a lot cleaner.
* init/job.h: Update prototypes.
* init/tests/test_job.c (test_child_reaper, test_child_minder):
Combine unit tests from both functions into single new
(test_child_handler): function.
* init/main.c (main): Call the combined function on child events
instead of separate ones.
* init/job.c (job_child_minder): Add informational message and
improve style and documentation.
2007-12-02 Scott James Remnant <scott@netsplit.com>
* init/enum.h (JobWaitType): Introduce a new enum that specifies
how to transition the job from spawned to running; either we don't
wait, or we wait for it to emit the stopped signal.
* init/job.h (JobConfig): Add the wait_for member.
Add protoype for job_child_minder.
* init/job.c (job_config_new): Initialise to JOB_WAIT_NONE.
(job_child_minder): New function to catch when a process is stopped
by a signal, and move it to the next state when it does so.
* init/tests/test_job.c (test_config_new): Check the initialisation
of wait_for to JOB_WAIT_NONE.
(test_child_minder): Tests for the new function.
(test_change_state): Copy the daemon test case to refer to waiter.
* init/main.c (main): Call job_child_minder whenever the job is
stopped by a signal
* init/parse_job.c (stanza_wait): Parse a new "wait" stanza that
specifies what to wait for before leaving the spawned state.
* init/tests/test_parse_job.c (test_stanza_wait): Check the new
stanza.
2007-11-29 Scott James Remnant <scott@netsplit.com>
* init/tests/test_job.c (test_change_state): Add a few sets to NULL
so gcc is happy.
2007-11-15 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_child_reaper): Update argument names and types
to match new NihChildHandler pattern; switch on event instead,
which can now have three values not two (it always could, this was
a bug) to output warning and assume that status is always non-zero
if killed so no need to check that separately.
* init/job.h: Update prototype.
* init/tests/test_job.c (test_child_reaper): Update calls to
job_child_reaper to pass an NihChildEvents member instead of FALSE
or TRUE for killed.
* init/main.c: Adjust call to nih_child_add_watch to indicate which
events we want to pass to the reaper; we don't use NIH_CHILD_ALL
since we're going to add ptrace stuff to a different function.
2007-11-07 Scott James Remnant <scott@netsplit.com>
* init/main.c (main): Tidy up.
2007-11-04 Scott James Remnant <scott@netsplit.com>
Complete the simplification of job config; rather than try and
precompute job replacements, keeping them all in the same hash table
and chaining them together, we just work it out when it's actually
necessary based on what's in the conf_sources list.
* init/job.h (JobConfig): Remove the replacement and replacement_for
members and put a deleted member in instead.
* init/job.c (job_config_new): Initialise deleted to FALSE; don't
replace the job into the hash table, since we only want the current
one in there now.
(job_config_find_by_name): Now that there is only ever one job
config in the hash table, we don't need any special function and
can just use nih_hash_lookup directly, so drop this function.
(job_config_should_replace): Rename to job_config_replace
(job_config_replace): Rework, it now checks to see whether there
are instances, and if not removes the job from the hash table
before selecting a new one (which might be the same job).
* init/tests/test_job.c (test_config_new): Update test to check
deleted starts off as FALSE and that the job isn't in the hash.
(test_config_find_by_name): Drop.
(test_config_should_replace): Rename and rewrite to test replacement
actually works as we expect.
(test_change_state): Update tests for entering the waiting mode and
replacing jobs.
(test_find_by_pid, test_find_by_id, test_handle_event)
(test_handle_event_finished): Add jobs to the hash table, otherwise
we can't find them
(test_child_reaper): Add job to the hash table, and also create a
source for it since we end up with it in the waiting state so need
to be able to keep it.
* init/Makefile.am (test_process_LDADD, test_job_LDADD)
(test_event_LDADD): Need the full .o file list now.
* init/conf.c (conf_file_destroy): Rewrite to mark the job deleted,
call job_config_replace if it's the current job and free it if
it isn't the current job either before or after that call.
(conf_reload_path): Handle job replacement here; look up the
old job in the hash table, if it exists attempt a replacement
otherwise add the new job to the hash table.
* init/tests/test_conf.c (test_source_reload_job_dir)
(test_source_reload_conf_dir, test_source_reload_file): Update
tests to check job->deleted and use nih_hash_lookup to see whether
it's the current job.
(test_file_destroy): Write tests to check the common cases, we don't
need to worry about the intermediate now since they can't happen.
* init/parse_job.c (parse_job): Massively simplify, this only creates
the config and parses it now.
* init/tests/test_parse_job.c (test_parse_job): Remove the replacement
checks.
* init/tests/test_event.c (test_poll): Add configs to the hash
table so they can be found.
* TODO: Update.
2007-11-03 Scott James Remnant <scott@netsplit.com>
* init/conf.h (ConfSource): Remove priority, we'll place these
in a linked list and use that order instead.
(ConfSourcePriority): Drop accordingly.
(ConfItem): Drop this structure; permitting jobs and states to be
defined inside larger conf files made things complicated for no
benefit; move the item union into
(ConfFile): here, instead of the items list.
(ConfItemType): Drop accordingly.
* init/conf.c (conf_init): Store sources in a linked list, instead
of a hash table; no idea why it ever was.
(conf_source_new): Drop priority argument and add to list not hash.
(conf_file_new): Set data to NULL instead of initialising items,
set destructor to conf_file_destroy.
(conf_item_destroy): Rename to conf_file_destroy
(conf_file_destroy): and adjust to refer to ConfItem instead,
getting the item type through the source.
(conf_item_new): Drop.
(conf_reload): Iterate as linked list not hash table.
(conf_reload_path): Simplify handling of old files and items a
little, just look it up and always free if it exists before parsing
the new file.
(conf_file_get): No longer any need for this function.
* init/tests/test_conf.c (test_file_get, test_item_new): Drop
test functions for those that have been removed.
(test_item_destroy): Rename to test_file_destroy.
(test_source_new): Don't pass or check priority, or hash lookup.
(test_file_new): Check data is set correctly.
(test_source_reload_job_dir, test_source_reload_conf_dir)
(test_source_reload_file): Update tests accordingly.
* init/parse_conf.c (stanza_job): Drop the job stanza, jobs
may only be defined in dedicated directories.
* init/tests/test_parse_conf.c (test_parse_conf): Simply check to only
make sure the file is parsed.
(test_stanza_job): Drop function.
* init/main.c: Update calls to conf_source_new.
* init/init.supp: Update intermediate function in suppression.
2007-10-26 Scott James Remnant <scott@netsplit.com>
* init/process.c (process_spawn): Mask out all signals across the
fork() rather than just SIGCHLD; reset the signal handlers to default
before unmasking again. The original rationale was we needed to
avoid SIGCHLD occurring before we'd stashed the pid, but that's no
longer a problem; the new rationale is that we want to avoid the
signal handlers running in the newly forked child.
2007-10-20 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_init): The job's name is the first item in the
structure again, so we can use nih_hash_string_key.
(job_config_name): Drop this function, then.
* init/conf.h (ConfSourcePriority): Add a priority enum
(ConfSource): Add priority member.
* init/conf.c (conf_source_new): Take priority as an argument and
set it in the structure.
* init/tests/test_conf.c (test_source_new): Make sure priority
is set from the argument.
(test_file_new, test_file_get, test_item_new)
(test_source_reload_job_dir, test_source_reload_conf_dir)
(test_source_reload_file, test_source_reload, test_item_destroy):
Pass in a priority when creating a ConfSource.
* init/tests/test_parse_conf.c (test_parse_conf): Likewise.
* init/main.c (main): Set relative priorities for the configuration
directories.
* init/conf.h (conf_file, conf_item): Add source and file members
respectively that point to the parent structure.
* init/conf.c (conf_file_new, conf_item_new): Set the members.
* init/tests/test_conf.c (test_file_new, test_file_get)
(test_item_new): Make sure the new members are set properly.
* util/Makefile.am (install-data-hook, install-exec-hook): Apply
transform to source and destination of both manpage and program
symlinks.
* compat/sysv/Makefile.am (install-data-hook, install-exec-hook):
Likewise for the compatibility symlinks.
* TODO: Update.
* init/tests/test_process.c (test_spawn): Make the event a child
of the operator so it doesn't get freed first.
* init/job.c (job_instance): Increment an instances counter each
time we spawn an instance.
(job_change_state): Decrement the instances counter again.
(job_detect_stalled): Drop the main loop function, since we perform
active detection of stall now.
* init/job.h: Update header.
* init/tests/test_job.c (test_change_state): Check that we get the
stalled event for the last instance.
(test_detect_stalled): Drop the test.
* init/main.c: Remove job_detect_stalled from the main loop.
* init/event.c (event_operator_destroy): Destructor for an
EventOperator that unblocks and unreferences the event first.
(event_operator_new): Set the operator.
(event_operator_copy): Remove error handling since it's unnecessary
with the destructor in place.
* init/event.h: Add prototype.
* init/tests/test_event.c (test_operator_destroy): Make sure it
works properly.
(test_operator_copy): Don't unblock or unref events before freeing
them, since that's now taken care of when it's referenced.
* init/job.c (job_new): Remove unnecessary error handling.
* init/tests/test_job.c (test_run_process): Reference the event
when setting it, otherwise we'll assert when we try to free it.
* TODO: Update.
* init/job.c (job_new): Drop the parent argument for consistency.
(job_instance): Update call to job_new.
* init/job.h: Update prototype.
* init/tests/test_job.c (test_new): Adjust call, check the parent
and make sure that start_on and stop_on are copied over properly.
* TODO: Update.
* init/conf.c (conf_file_get): Split out the allocation code from here
(conf_file_new): into this new function.
* init/conf.h: Add prototype.
* init/tests/test_conf.c (test_file_new): New tests.
* TODO: Update.
* init/job.c (job_change_state): Hardcode the next state when we
catch a runaway job to be JOB_WAITING.
(job_next_state): Change next state for JOB_STARTING when goal is
JOB_STOP to be JOB_STOPPING for consistency with the others; otherwise
if our goal is stopped during our starting event, we'll never emit
a stopping event to match it.
* init/tests/test_job.c (test_next_state): Update test case.
* doc/states.dot: Adjust the state transitions.
* doc/states.png: Regenerate.
* TODO: Update.
2007-10-19 Scott James Remnant <scott@netsplit.com>
Dealing with instances has always been tricky since they're copies
that exist in the hash table; this patch changes that so the job's
configuration is separated from its state. The only difference
between instance and non-instance jobs now is that non-instance
jobs only ever have one entry in their instances list.
* init/job.h (Job): Separate out the members that come from the
configuration into a new JobConfig structure which can be shared
amongst all of the instances; this means we can drop instance_of.
(JobConfig): Add instances list.
(JobProcess): Remove pid member, replaced by pid list in Job.
Update prototypes of functions to match.
* init/job.c (job_new): Split off initialisation of configuration
pieces into new job_config_new function leaving the state here;
copy the start_on and stop_on members from JobConfig
(job_copy): Drop this function, we don't need to copy jobs now.
(job_name): Rename to job_config_name.
(job_init): Set key function to job_config_name.
(job_process_new): Drop initialisation of pid.
(job_process_copy): Drop this function entirely, we don't need it.
(job_find_by_name): Rename to job_config_find_by_name; massively
simplify now we won't find instances or deleted jobs in the list.
(job_should_replace): Rename to job_config_should_replace; simplify
now that we can do a simple check to see whether a job exists or not
(job_find_by_pid, job_find_by_id): Loop through the instances after
looping through the hash table.
(job_instance): Simplify, now all it needs to do is call job_new()
if there isn't anything in the instances list, or it's multi-instance.
(job_change_goal): Document that job should not be used on return.
No need to check for instance jobs anymore. Place the job id in
the output.
(job_change_state): Document that job should not be used on return.
Place the job id in the output. Check for information in the job's
config. Merge the waiting and deleted states, so that a job instance
is automatically deleted when it finishes.
(job_next_state): Assert that we never call job_next_state when
in JOB_WAITING since there's no possible next state. Check config
for whether a main process exists.
(job_emit_event): Obtain config-replaced pieces from the job's config
(job_run_process): Obtain process information from the job's config
but store the pid in the Job. Put job id in the output.
(job_kill_process, job_kill_timer): We don't need to obtain the
JobProcess just the pid from the job. Put job id in the output.
(job_child_reaper): Put job id in the output. Check job config.
(job_handle_event): Iterate job instances and process their stop_on
operators, but process the start_on from the job configs.
(job_handle_event_finished): Loop through the instances too.
(job_detect_stalled): Check start_on from the config and just
check whether there are any instances in the list.
(job_free_deleted): No deleted state, so drop this function.
* init/tests/test_job.c (test_new): Split into test_new and
new test_config_new function. Create JobConfig object and spawn
Job instances from that.
(test_copy): Drop the tests.
(test_process_new): Drop check of pid.
(test_process_copy): Drop test.
(test_find_by_name): Rename to test_config_find_by_name.
(test_should_replace): Rename to test_config_should_replace.
(test_instance): Create JobConfig object, and adjust tests to ensure
that we always get a Job object.
(test_find_by_pid, test_find_by_id, test_change_goal): Create
JobConfig object and spawn Job instances from that.
(test_change_state): Create JobConfig object and spawn Job
instances from that. Adjust tests that previously checked for
JOB_WAITING to check for job being freed. Drop checks for JOB_DELETED.
(test_next_state): Create JobConfig object and spawn Job instances
from that. Drop JOB_DELETED and JOB_WAITING checks.
(test_run_process, test_kill_process, test_child_reaper)
(test_handle_event, test_detect_stalled): Create JobConfig object
and spawn Job instances from that.
(test_free_deleted): Drop.
* init/main.c: Don't add job_free_deleted to the main loop.
* init/enum.h (JobState): Drop JOB_DELETED.
* init/enum.c (job_state_name, job_state_from_name): Drop JOB_DELETED.
* init/tests/test_enum.c (test_state_name, test_state_from_name):
Drop tests that use the JOB_DELETED value.
* init/process.c (process_spawn, process_setup_limits)
(process_setup_environment, process_setup_console): Get details
from the job config. Put job id in the output.
* init/tests/test_process.c (test_spawn, test_kill): Create
a JobConfig object and make Job instances from that.
* init/tests/test_event.c (test_poll): Create a JobConfig object
and make Job instances from that.
(test_operator_copy): Set pointers to NULL to avoid gcc complaining.
* init/conf.h (ConfItem): Make the type for a job be JobConfig.
* init/conf.c (conf_item_destroy): Don't attempt to replace the
new middle-man target, if it was due to be replaced it would have
already been. If we can replace the config, ensure nothing points
at it and then free it, rather than kicking state.
* init/tests/test_conf.c (test_source_reload_job_dir)
(test_source_reload_conf_dir, test_source_reload_file)
(test_source_reload, test_item_destroy): Call job_config_new to
create JobConfig objects, track when they are freed rather than
marked in the deleted state. Create instances with job_instance,
and fetch from the instances list. Expect the job to be freed
with the item.
* init/tests/test_parse_conf.c (test_parse_conf)
(test_stanza_job): Change expected type from Job to JobConfig.
* init/parse_job.c: Update prototypes of all functions to refer to
JobConfig instead of Job.
(parse_job): If the old job already has a replacement, remove the
replacement from the hash table -- but don't free it because it's
linked by a ConfItem -- this is temporary. Likewise for when we
replace the old job.
* init/parse_job.h: Update prototype.
* init/tests/test_parse_job.c: Update all functions to use JobConfig
instead of Job.
(test_parse_job): Create an instance.
* doc/states.dot: Remove the deleted state.
* doc/states.png: Regenerate.
* TODO: Update with notes from the conversion.
2007-10-16 Scott James Remnant <scott@netsplit.com>
Update to catch up with changes in libnih that make code a little
bit easier to follow (we hope).
* init/tests/test_process.c (test_spawn, test_kill): Replace calls
to nih_list_free() with nih_free()
* init/event.c (event_poll): Replace nih_list_free with nih_free
since the former function has gone from libnih.
(event_new): Adjust setting of the destructor.
(event_operator_new): Set destructor for the tree node.
* init/tests/test_event.c (test_new, test_find_by_id, test_ref)
(test_unref, test_block, test_unblock, test_poll)
(test_operator_match): Replace nih_list_free with nih_free.
(test_poll): Use TEST_FREE_TAG and TEST_FREE rather than abusing
destructors.
* init/job.c (job_new): Set destructor to nih_list_destroy.
(job_copy, job_free_deleted): Use nih_free instead of nih_list_free
* init/tests/test_job.c (test_new, test_copy, test_find_by_name)
(test_find_by_pid, test_find_by_id, test_instance)
(test_change_goal, test_change_state, test_next_state)
(test_should_replace, test_run_process, test_kill_process)
(test_child_reaper, test_handle_event)
(test_handle_event_finished, test_detect_stalled)
(test_free_deleted): Replace all uses of nih_list_free with nih_free
(test_child_reaper, test_free_deleted): Replace destructor abuse
with TEST_FREE, etc.
* init/conf.c (conf_reload_path): Use nih_free instead of nih_list_free
(conf_source_new, conf_file_get, conf_item_new): Set destructor
(conf_source_reload, conf_delete_handler): Use nih_free not the
custom conf_file_free() function.
(conf_reload_path): Use nih_free not the custom conf_item_free()
function.
(conf_delete_handler): Use nih_free not nih_watch_free()
(conf_source_free, conf_file_free): Drop these functions, since
all the free chaining happens properly with destructors.
(conf_item_free): Rename to conf_item_destroy and turn into destructor
* init/conf.h: Update prototypes.
* init/tests/test_conf.c (test_source_new, test_file_get)
(test_item_new, test_source_reload_job_dir)
(test_source_reload_conf_dir, test_source_reload_file)
(test_item_free): Replace nih_list_free calls with nih_free
(test_source_reload_job_dir, test_source_reload_conf_dir)
(test_source_reload_file, test_source_reload, test_item_free): Replace
calls to conf_source_free with nih_free
(test_source_free, test_file_free): Drop functions.
(test_item_free): Rename to test_item_destroy
(test_item_new): Assign a job before freeing, otherwise the destroy
function will foul up as it expects one.
* init/parse_conf.c (stanza_job): Replace nih_list_free with nih_free
* init/tests/test_parse_conf.c (test_parse_conf)
(test_stanza_job): Replace conf_source_free() with nih_free()
(test_parse_conf, test_stanza_job): Replace conf_item_free()
with nih_free()
* init/parse_job.c (parse_job, parse_on_paren, parse_on_collect):
Replace nih_list_free with nih_free
(parse_on): always cut out the stack head before returning (it won't
be empty on error) otherwise we end up with a bunch of list entries
pointing to it -- and it's way out of scope when we try and free them
(parse_on_operator, parse_on_operand): Use the job as the context
not the operator for consistency of freeing.
* init/tests/test_parse_job.c: Replace all instances of nih_list_free
with nih_free (too many functions to list).
2007-10-15 Scott James Remnant <scott@netsplit.com>
Strip out all of the IPC code, removing it and consigning it to the
great revision control history in the sky. We're going to switch
from home-brew to D-BUS. so all this is somewhat obsolete. Rather
than maintain this while we carry on developing, we'll strip it out
now and put the D-BUS code in ater once the rest of the core changes
are done (otherwise we'd just be dragging those through maintenance
too).
* Makefile.am (SUBDIRS): Remove the upstart sub-directory entirely;
comment out util, compat/sysv & logd since we'll fix them up later
* configure.ac (AC_CONFIG_FILES): Remove from here too.
* upstart/enum.c, upstart/enum.h, upstart/tests/test_enum.c: Move
these files into the init/ sub-directory; strictly speaking we'll
probably need to share them again later in some way, but for now
they can live with the rest of the daemon code.
* upstart/: Delete.
* init/Makefile.am (init_SOURCES): Remove control.c, control.h,
notify.c and notify.h; add enum.c and enum.h
(TESTS): Remove test_control and test_notify; add test_enum
(test_control_SOURCES, test_control_LDFLAGS, test_control_LDADD)
(test_notify_SOURCES, test_notify_LDADD): Remove.
(test_enum_SOURCES, test_enum_LDFLAGS, test_enum_LDADD): Add details
(init_LDADD): Remove libupstart
(test_process_LDADD, test_job_LDADD, test_event_LDADD)
(test_parse_job_LDADD, test_parse_conf_LDADD, test_conf_LDADD): Remove
libupstart, control.o and notify.o; add enum.o
* init/control.c, init/control.h, init/tests/test_control.c: Delete
* init/notify.c, init/notify.h, init/tests/test_notify.c: Delete
* init/enum.c, init/job.c, init/job.h: Update include path for enum.h
* init/parse_job.c: Remove unnecessary enum.h include
* init/tests/test_enum.c: Update to reflect where it is.
* init/main.c (main): Drop control socket opening.
* init/tests/test_job.c: Remove unnecessary control.h include
* init/event.c (event_pending, event_finished): Remove calls to
notify_event and notify_event_finished
* init/job.c (job_change_goal, job_change_state): Remove calls
to notify_job.
* init/tests/test_parse_conf.c: Remove calls to notify_init
* init/tests/test_parse_job.c: Remove calls to notify_init
* init/tests/test_event.c (test_poll): Strip out the part of the
test that checks processes are notified.
(check_event, check_event_finished): Remove.
* configure.ac: Bump Autoconf dependency to 2.61 to match libnih
* HACKING: Bump dependency in docs too.
* NEWS: Copy in news from 0.3.9; that release doesn't appear in
this ChangeLog since it was made on a separate branch by backporting
bug fixes made here.
* configure.ac: Bump version to 0.5.0, which is where development
is heading for.
2007-10-12 Scott James Remnant <scott@netsplit.com>
* HACKING: Change URL for libnih.
2007-10-08 Scott James Remnant <scott@netsplit.com>
* configure.ac (AM_GNU_GETTEXT_VERSION): Bump to 0.16.1 since this
version of gettext is needed for compatibility with Automake 1.10
* HACKING: Bump version in the docs too.
* compat/sysv/Makefile.am: Only create symlinks if COMPAT_SYSV is
enabled, otherwise we leave dangling ones.
* Makefile.am (ACLOCAL_AMFLAGS): Specify that aclocal install
ordinarily system-wide macros into m4 (libtool.m4, specifically).
This makes it easier for packagers to modify autoconfery since
aclocal is no longer a destructive event.
* configure.ac (AM_INIT_AUTOMAKE): Increase Automake requirement to
1.10 to ensure we have aclocal --instal
* HACKING: Increase Automake version in the docs.
2007-09-21 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_detect_stalled, job_free_deleted): Call job_init()
on entry, since we don't have a Job pointer passed to us, we need
to make sure we don't dereference a potentially NULL list.
2007-06-22 Scott James Remnant <scott@netsplit.com>
* TODO: Update.
* init/job.h: Update prototype of job_change_goal.
(Job): Remove cause member.
* init/job.c (job_change_goal): Drop additional argument since cause
is no longer used.
(job_change_state, job_child_reaper, job_handle_event): Only pass
two arguments to job_change_goal.
* init/control.c (control_job_start, control_job_stop): Only pass
two argumenst to job_change_goal.
* init/tests/test_job.c (test_change_goal, test_change_state): Only
pass two arguments to job_change_goal.
* init/job.c (job_new): Drop setting of cause.
(job_change_cause): Drop this function entirely.
(job_change_goal, job_change_state): Drop calls to job_change_cause
(job_change_state, job_child_reaper): Don't pass job->cause to
job_change_goal calls.
* init/tests/test_job.c: Remove all tests that checked the value of
job->cause, since that variable is going away.
(test_change_goal): Remove the specific tests that checked whether
cause was updated or not.
* init/job.c (job_run_process): Replace the arguments from the event
with a list of event names.
* init/tests/test_job.c (test_run_process): Update test case to
supply arguments from the list of events.
* init/process.c (process_setup_environment): Drop the UPSTART_EVENT
environment variable; it doesn't make sense when you can have multiple
events.
(process_setup_environment): Put all variables from the job's start
events into the job's environment; replacing the UPSTART_EVENT variable
* init/job.c (job_change_cause): Don't notify the job event
subscribers when changing the cause.
* init/notify.c (notify_job_finished): Instead notify them when
the job reaches a rest state.
* init/notify.c (notify_job): Call notify_job_event regardless,
since this now looks over the start_on and stop_on fields.
(notify_job_event): Rewrite to iterate over start_on and stop_on,
and notifying for each cause event found.
(notify_job_event_caused): Static function that is the guts of the
above function.
* init/tests/test_notify.c (test_job, test_job_event): Modify tests
to refer exclusively to the start_on/stop_on expressions rather than
the cause.
* init/job.c (job_change_cause): Only notify the job event and
update the cause member, we don't need to ref or block it anymore
since that's handled by start_on and stop_on.
* init/tests/test_job.c (test_change_goal): Drop checks on cause
being referenced and blocked.
(test_change_state, test_child_reaper, test_handle_event): Update
test cases to not reference ->cause, and not count any references
or blockers towards it.
* init/tests/test_event.c (test_poll): Update expected reference
and block counts for events handled by jobs.
* init/tests/test_process.c (test_kill): Make sure that all processes
in the process group are killed, rather than just the lone one.
* init/process.c (process_kill): Send the signal to all processes
in the same process group as the pid.
* init/tests/test_job.c (test_change_state, test_kill_process):
After spawning a child, call setpgid() to put it in its own process
group otherwise we could end up TERMing ourselves.
* init/tests/test_job.c (test_child_reaper): Update test cases to
include checking of the start_on and stop_on expression trees.
* init/job.c (job_child_reaper): Mark all blocked events in the
start_on and stop_on trees as failed; since these are copies of
the cause event, we can drop that setting already.
* TODO: Update again, still thinking about the atomicity of event
expressions.
2007-06-21 Scott James Remnant <scott@netsplit.com>
* init/tests/test_job.c (test_change_state): Include tests on a job's
start_on and stop_on event expression trees, and make sure that events
are unblocked and unreferenced at the appropriate moments.
* init/job.c (job_change_state): Unblock the events that started the
job in running (if a service), and reset when we reach waiting (leave
referenced otherwise so the environment is always present).
Unblock and unreference the events that stopped the job in
starting (for restarting), running (if coming from pre-stop) and
waiting.
* init/tests/test_job.c (test_handle_event): Rewrite tests using
event expressions, and make sure events are referenced and blocked
correctly matching how jobs are affected. Include tests for correct
instance behaviour.
(test_instance): Make sure that instances copy across the expression
state, and reset the parent.
* init/job.c (job_instance): After spawning a new instance, reset
the start_on expression of the master job.
* init/event.c (event_operator_copy): Change to making the parent
of copies nodes be the actual tree parent, rather than the top
parent; otherwise you can't free an entire tree in one go.
* init/tests/test_event.c (test_operator_copy): Check parents of
copied nodes.
* init/tests/test_job.c (test_copy): Update parent checks here too.
* init/tests/test_job.c (test_copy): Make sure that the job copy
references and blocks the event; and in the event of failure, doesn't
* init/job.c (job_copy): Reset the start_on and stop_on expressions
in the event of failure.
2007-06-20 Scott James Remnant <scott@netsplit.com>
* TODO: Update.
* init/parse_job.c (parse_on): New generic parsing function to deal
with event expressions, including operators, parentheses, etc.
(parse_on_operator): Function called by parse_on() to deal with an
operator or operand.
(parse_on_paren): Function called by parse_on() to deal with a
parenthesis.
(parse_on_operand): Function called by parse_on_operator() to deal
with a non-operator token.
(parse_on_collect): Function called by all of the above to collect
the operators on the stack and deposit them into the output box,
either for collection by a later operator or for returning from
parse_on().
(stanza_start, stanza_stop): Call the new parse_on() function to
deal with "start on" and "stop on", storing it in the appropriate
part of the job.
* init/tests/test_parse_job.c (test_parse_job): Replace list empty
checks for start_events/stop_events with NULL checks on the new
start_on/stop_on members.
(test_stanza_start, test_stanza_stop): Test new stanza code.
* init/errors.h (PARSE_EXPECTED_EVENT, PARSE_EXPECTED_OPERATOR)
(PARSE_MISMATCHED_PARENS): Add numerics and strings for the errors
that can be generated by parsing an event expression.
* init/conf.c (conf_reload_path): Handle the new errors properly,
including the line number where they occurred.
* logd/jobs.d/logd.in: Update "stop on" to work with the new parser.
* init/parse_job.c (stanza_emits): Each entry in the emits list
is now an NihListEntry with the event name as the string data
pointer, rather than an EventInfo structure (since that structure
is gone).
* init/tests/test_parse_job.c (test_stanza_emits): Update test
case to check for NihListEntry structures.
* init/parse_job.c: Where the stanza function parses an argument and
can possibly reject it, save the position and line number and do not
return that unless we're happy with the argument. This ensures errors
are raised pointing *at* the argument, rather than past it.
* init/tests/test_parse_job.c: Fix several test case errors where
the buffer was built incorrectly. Pedantically check pos and lineno
after successful parsing, and after errors, to make sure they are
where they should be.
2007-06-18 Scott James Remnant <scott@netsplit.com>
* init/job.h (Job): Replace the start_events and stop_events NihLists
with start_on and stop_on EventOperators.
* init/job.c (job_new): Drop list initialising, and instead just set
the new start_on/stop_on members to NULL.
(job_copy): Copy the entire event operator tree to the new job,
including references and blockers. emits has changed to a list of
NihListEntry with embedded strings, so copy them that way.
(job_run_process): Drop "->info."
(job_handle_event): Instead of iterating the events lists, call
event_operator_handle and check the return value and top node value.
(job_detect_stalled): Modify to iterate the start_on tree.
* init/tests/test_job.c (test_change_state, test_detect_stalled):
Drop references to "->info." since we can get the variables directly.
(test_new): Check that start_on and stop_on are NULL.
(test_copy): Adjust tests of copying start_on and stop_on trees as
well as the emits list.
(test_handle_event, test_handle_event_finished)
(test_detect_stalled): Change references from start_events to start_on,
stop_events to stop_on and construct using EventOperators instead.
(test_handle_event): Update number of blockers now that the event
expressions themselves will block the event.
* init/tests/test_event.c (test_poll): Update number of blockers since
both the events and cause will block it for now; also change
start_events and stop_events to start_on and stop_on respectively.
* init/event.c (event_operator_copy): Copy the children nodes as well.
* init/tests/test_event.c (test_operator_copy): Test copying
with children nodes.
* init/tests/test_control.c (test_event_emit): Drop "->info."
* init/notify.c (notify_event, notify_event_finished): Drop
"->info." from event references.
* init/process.c (process_setup_environment): Drop "->info." from
cause references
* init/tests/test_process.c (test_spawn): Likewise.
* init/event.h (Event): Directly include the name, args and env
fields rather than using an interim structure; this makes more sense
since we use them differently than a match does.
(EventOperatorType, EventOperator): New structure to build event
expression trees that combine a match with "or" and "and" boolean
operators; solve some problems by holding the reference and blocker
on the matched event inside this structure directly and provide
methods to unblock and reset them.
(EventInfo): Drop this structure completely now that it is unused.
* init/event.c (event_info_new): Rename this structure to
event_operator_new() and initialise the new fields properly.
(event_info_copy): Likewise rename to event_operator_copy and deal
with copying event references and blockers over to the new structure,
since the state is useful to copy.
(event_match): Rename to event_operator_match and switch the arguments
around since it makes slightly more sense that way.
(event_operator_update): Function to update the value of an EVENT_OR
or EVENT_AND operator based on the value of the two children.
(event_operator_handle): Function to iterate an entire expression
tree looking for a given event, and update the values of other
operators if matched.
(event_operator_unblock): Function to iterate an expression tree
and release any events we're blocking.
(event_operator_reset): Function to iterate an expression tree,
unreferencing any events and resetting all values back to FALSE.
(event_new, event_pending, event_finished): Update references to
the Event structure to discard the intermediate "->info."
* init/tests/test_event.c (test_info_new): Rename to
test_operator_new() and test various features of the function added
in the converstion.
(test_info_copy): Likewise rename to test_operator_copy() and add a
few more tests, especially that blockers and references are copied.
(test_match): Rename to test_operator_match() and adjust argument
order to match the change.
(test_new) Call event_init() to avoid a valgrind error and update
references to drop "->info."
(test_poll): Use EventOperators in the job to test event polling,
rather than the old structures.
(test_operator_update, test_operator_handle, test_operator_unblock)
(test_operator_reset): Test behaviour of the new functions.
2007-06-13 Scott James Remnant <scott@netsplit.com>
* TODO: Update utmp/wtmp thoughts.
2007-06-12 Scott James Remnant <scott@netsplit.com>
* init/paths.h: Remove extra /, oops.
* init/Makefile.am (install-data-local): Make destination
configuration directories as part of "make install".
(AM_CPPFLAGS): Define LEGACY_CONFDIR to be $(sysconfdir)/event.d
* logd/Makefile.am (jobs.d/logd): Replace mkdir_p with MKDIR_P
* init/main.c: Use macro to pick up /etc/event.d so it can be moved
by configure
* TODO: Update.
* init/Makefile.am (AM_CPPFLAGS): Define CONFDIR to be
$(sysconfdir)/init, replacing the old CFG_DIR definition.
* init/paths.h (CFG_DIR): Replace with CONFDIR definition,
and set the default to /etc/init
* init/main.c: Load configuration from /etc/init/init.conf,
/etc/init/conf.d and /etc/init/jobs.d; retain loading from /etc/event.d
for the time being.
* init/man/init.8: Change reference to directory.
* logd/Makefile.am: Replace references of eventdir with jobsdir,
and event.d with jobs.d
* logd/event.d: Rename to logd/jobs.d
* init/conf.c (conf_reload): Ignore ENOENT, it's not interesting
in the general case.
* init/tests/test_conf.c (test_source_reload): Test the general
reload function.
* init/tests/test_conf.c (test_source_free): s/unlink/rmdir/
(test_source_reload_file): Test that configuration files work, and
are parsed with anything alongside ignored automatically.
* init/conf.c (conf_file_filter): As well as not filtering out the
source path itself, we also need to not filter out the path we're
watching which is different in the case of files; we need to know
about it because we handle its removal.
(conf_delete_handler): Compare the path deleted against the path
we're watching, rather than the source path, since this means the
watch needs to be freed.
* compat/sysv/shutdown.c: Use nih pidfile functions since they're
more reliable than doing it ourselves.
2007-06-11 Scott James Remnant <scott@netsplit.com>
* init/conf.c (conf_reload_path): Call parse_conf for mixed files
and directories. Make a correction to the old_items code, was
passing the wrong arguments to nih_list_add; the effect we wanted
was that we add the old items head into the list, and remove the
existing head (what we did was add the first item to the old_items
list and then cut the rest out).
* init/tests/test_conf.c (test_source_reload_dir): Rename to
test_source_reload_job_dir, since that's what this does.
(test_source_reload_conf_dir): Add another function that tests
directories of mixed configuration.
* init/parse_conf.c (parse_conf): Parse a configuration file that
defines jobs by name.
(stanza_job): Job stanza, slightly trickier than it would appear to
need to be, to parse the block in-place and keep pos/lineno
consistent.
* init/parse_conf.h: Prototype for external function.
* init/tests/test_parse_conf.c: Test suite for mixed configuration
parsing.
* init/Makefile.am (init_SOURCES): Build and link parse_conf.c and
parse_conf.h
(TESTS): Build and run parse_conf tests
(test_parse_conf_SOURCES, test_parse_conf_LDFLAGS)
(test_parse_conf_LDADD): Details for parse_conf test suite.
(test_conf_LDADD): Add parse_conf.o and conf.o since this calls
them now.
* init/conf.c (conf_source_reload, conf_source_reload)
(conf_reload_path): Add some debugging messages.
* init/conf.c (conf_source_new): Add missing call to conf_init()
* init/conf.c (conf_item_new): Drop source parameter, since it's
unused in the function and makes it harder to call this when we
only have one data pointer.
(conf_reload_path): Drop source from conf_item_new() call.
* init/conf.h: Update prototype.
* init/tests/test_conf.c (test_item_new, test_item_free)
(test_file_free): Drop source parameter from calls.
2007-06-10 Scott James Remnant <scott@netsplit.com>
* init/main.c (main): Add a handler for the SIGHUP signal
(hup_handler): Handler for SIGHUP, just calls conf_reload().
* init/main.c (main): Read the configuration again.
* TODO: Update.
* init/tests/test_conf.c (test_source_reload_dir): Reset the priority
and clean up consumed inotify instances.
(test_source_free, test_file_free, test_item_free): Test the free
functions on their own, paying special attention to conf_item_free()
even though this really duplicates other tests.
* init/conf.c (conf_reload_path): In the case where we fail to map
the file into memory, we still need to purge all the items that
previously existed.
* init/tests/test_conf.c (test_source_reload): Rename to
test_source_reload_dir, so that we can keep this and the file
tests separate to make it easier to deal with.
(test_source_reload_dir): Add tests for physical and parse errors
when re-loading jobs with and without inotify, and for inotify-based
modification handling of jobs.
* init/tests/test_conf.c (test_source_reload): Add test for walk
of non-existant directory with and without inotify; also test for
what happens when the top-level directory is deleted, again with
and without inotify.
* init/conf.c (conf_delete_handler): Handle the case of the top-level
directory being deleted by freeing the watch (so next time we asked
to reload, we can restore it).
* init/tests/test_conf.c (test_source_reload): Add a test for
deletion of a running job.
* init/conf.c (conf_item_free): Fix this up; when deleting an item
from a source, we first mark it for deletion unless it's already
marked for replacement. Then if it's the replacement for something
else, we mark that to be replaced by whatever we're being replaced
by (so there are no references to us) and change that state if
necessary. Finally we replace our own item and free the record
before returning.
* init/tests/test_conf.c (test_source_reload): Check that we handle
the cases of modiciation of a running job, modification of a
replacement of a running job and deletion of a replacement for a
running job.
* init/parse_job.c (parse_job): Instead of freeing the previous
replacement, which could leave invalid references to it, mark it
for deletion and change the state.
* init/tests/test_parse_job.c (test_parse_job): Adjust the test so
that we hold a reference to the replacement job and make sure that
the state is changed to deleted, rather than checking for a destructor
being called on it.
* init/init.supp (conf-init): Add valgrind suppression for the
configuration sources hash table.
* init/conf.c (conf_item_free): Don't overwrite any previous
replacement, only mark us for deletion if we wouldn't otherwise
be replaced. Add some commented possible code for testing.
* init/tests/test_conf.c (test_source_reload): Test replacement of
jobs works properly; test modification with direct write and with
atomic rename replace; test deletion.
* init/conf.c (conf_reload_path): It turns out that the flag trick
doesn't work for items since we often reparse them within the same
file tag (it works with files because they're atomic and reparsed).
Store the old items in a different list instead.
(conf_source_free): We need to be careful about freeing sources,
so have a function to do it properly.
(conf_item_new): Since the flag member isn't useful, don't bother
setting it.
* init/conf.h: Add conf_source_free prototype.
(ConfFile): Remove flag member.
* init/tests/test_conf.c (test_source_reload): Add test for inotify
create detection.
* init/conf.c (conf_file_delete): Rename to conf_file_free and match
the pattern of those kinds of functions.
(conf_item_delete): Likewise rename to conf_item_free and match the
pattern of these kinds of functions.
* init/conf.h: Add prototypes.
* init/conf.c (conf_reload_path): Fix bug with job name generation.
Allow non-parsing errors to be returned from the function.
(conf_item_delete): Drop all replacement management code, we'll put
this back through testing.
* init/tests/test_conf.c (test_source_reload): Test reloading adds
the right inotify watch and parses the files, also check that loading
without inotify and mandatory reloading work.
* init/conf.c (conf_source_reload): Move the item deletion detection
code from this function, where it would only happen on a mandatory
reload
(conf_reload_path): to this function, where it will happen every time
the file is parsed; which is actually what we want.
2007-06-08 Scott James Remnant <scott@netsplit.com>
* init/conf.h (ConfItem): Drop the name and replace it with a type.
(ConfItemType): Enum for different types of configuration items
(ConfFile): Change items from a hash table to a list.
* init/conf.c (conf_file_get): Initialise the items member as a list.
(conf_item_set): Rename to conf_item_new again.
(conf_item_new): Allocates a new ConfItem and adds it to the file's
list, we won't reuse items anymore since it doesn't really make sense.
(conf_source_reload): Adjust clean-up code now that items is a list.
(conf_reload_path): Work out the name of jobs found by filename,
allocate a new item for them and parse the job into it. Perform
handling of errors by outputting a warning.
(conf_item_delete): Takes both source and file so we can make
intelligent decisions.
(conf_file_delete): Takes a source and passes it to conf_item_delete
(conf_delete_handler): Pass both source and file to conf_file_delet
* init/tests/test_conf.c (test_file_get): Check that the items
list is empty; rather than the hash being unallocated.
(test_item_set): Rename back to test_item_new and only allocate a
single item which should get added to the list.
2007-06-06 Scott James Remnant <scott@netsplit.com>
* init/parse_job.c (stanza_respawn): Permit the word "unlimited",
raise a specific error for illegal limit and illegal interval.
(stanza_pid, stanza_kill, stanza_normal, stanza_umask)
(stanza_nice, stanza_limit): Raise specific errors rather than
a generic "illegal value" error.
* init/tests/test_parse_job.c (test_stanza_respawn): Check that
we can use "unlimited", also check for new error return.
(test_stanza_pid, test_stanza_kill, test_stanza_normal)
(test_stanza_umask, test_stanza_nice, test_stanza_limit): Check
for new specific errors.
* init/errors.h: Replace CFG_ILLEGAL_VALUE with a series of parse
errors.
* init/conf.c: Comments.
* init/conf.c (conf_item_set): Call out to conf_item_delete() to
handle unsetting of an item's data.
(conf_source_reload): Add code to deal with mandatory reloading,
calls conf_file_delete() and/or conf_item_delete() as appropriate.
(conf_delete_handler): Call conf_file_delete() on the ConfFile that
we find.
(conf_file_delete): Function to delete all items in a file.
(conf_item_delete): Placeholder function to delete an item.
* init/conf.c (conf_file_new): Rename to conf_file_get; in practice
we never just want to allocate one of these, we always want to
return the existing entry if it exists.
(conf_item_new): Rename to conf_item_set; again in practice we always
want to update an existing item. This function will grow the "deal
with replacement" stuff.
(conf_reload): Start putting in place the code that will allow
mandatory reloads, as well as initial setup. This function iterates
over the sources and deals with errors.
(conf_source_reload): Function to reload an individual source, calls
out to one of the following two functions and will eventually perform
the deleted items scan.
(conf_source_reload_file): Set up a watch on a file, and reload it.
(conf_source_reload_dir): Set up a watch on a directory and reload it.
(conf_file_filter): Filter for watching parent directory of files.
(conf_create_modify_handler): File creation and modification handler.
(conf_delete_handler): File deletion handler.
(conf_file_visitor): Tree walk handler.
(conf_reload_path): Function that deals with files themselves,
currently just sorts out the ConfFile structure and maps the file
into memory.
* init/conf.h: Add new prototypes, update existing ones.
* init/tests/test_conf.c (test_file_new): Rename to test_file_get,
also test repeated calls when already in the table.
(test_item_new): Rename to test_item_set, also test repeated calls
when already in the table.
(test_source_reload): Start of test for reloading sources.
2007-06-05 Scott James Remnant <scott@netsplit.com>
* init/conf.c: Make a start on the new configuration management
routines, which will allow finer-grained tracking of configuration
and support mandatory reloading.
(conf_source_new, conf_file_new, conf_item_new): Start off with the
functions to allocate the tracking structures we need to use.
* init/conf.h: Structures and prototypes
* init/tests/test_conf.c: Test suite for allocation functions.
* init/Makefile.am (init_SOURCES): Build and link conf.c and conf.h
(TESTS): Run the conf test suite.
(test_conf_SOURCES, test_conf_LDFLAGS, test_conf_LDADD): Details for
the conf test suite.
2007-06-04 Scott James Remnant <scott@netsplit.com>
* init/parse_job.c (stanza_description, stanza_author, stanza_version)
(stanza_chroot, stanza_chdir, stanza_pid): Instead of erroring when
the string has already been allocated, free it and replace it with the
new one. Attempting to forbid duplicates is just too inconsistent,
especially for the integer ones which we compare against the default;
using the last one allows us to be entirely consistent.
(stanza_daemon, stanza_respawn, stanza_service, stanza_instance):
Don't error if the flag is already set, just ignore it.
(stanza_respawn, stanza_pid, stanza_kill, stanza_console)
(stanza_umask, stanza_nice): Don't compare the current value against
the default, just overwrite it!
(parse_exec, parse_script): Free existing process command string
before setting a new one over the top.
(parse_process, stanza_exec, stanza_script, stanza_limit): Instead of
erroring if the structure is already set and allocated, just don't
allocate a new one and allow its members to be overwritten.
* init/tests/test_parse_job.c (test_stanza_exec)
(test_stanza_script, test_stanza_pre_start)
(test_stanza_post_start, test_stanza_pre_stop)
(test_stanza_post_stop, test_stanza_description)
(test_stanza_author, test_stanza_version, test_stanza_daemon)
(test_stanza_respawn, test_stanza_service, test_stanza_instance)
(test_stanza_pid, test_stanza_kill, test_stanza_console)
(test_stanza_umask, test_stanza_nice, test_stanza_limit)
(test_stanza_chroot, test_stanza_chdir): Replace tests that check
for an error in the case of duplicate stanzas with tests that make
sure the last of the duplicates is used.
* init/errors.h (CFG_DUPLICATE_VALUE, CFG_DUPLICATE_VALUE_STR): Drop
this error, since we don't consider this a problem anymore.
* upstart/Makefile.am (libupstart_la_LIBADD): Add $(LTLIBINTL)
* init/Makefile.am (init_LDADD): Reorder and add $(LTLIBINTL)
* util/Makefile.am (initctl_LDADD): Reorder and add $(LTLIBINTL)
* compat/sysv/Makefile.am (reboot_LDADD): Reorder and add $(LTLIBINTL)
(runlevel_LDADD): add $(LTLIBINTL)
(shutdown_LDADD): Reorder and add $(LTLIBINTL)
(telinit_LDADD): Reorder and add $(LTLIBINTL)
* logd/Makefile.am (logd_LDADD): Add $(LTLIBINTL)
2007-06-03 Scott James Remnant <scott@netsplit.com>
* init/tests/test_job.c (test_run_process): Add a test case for a
crasher when the event has no arguments.
* init/job.c (job_run_process): Fix the bug, we need to check the
arguments before trying to append them.
* init/cfgfile.c, init/cfgfile.h, init/tests/test_cfgfile.c: Rename
to parse_job and strip out all functions except the parsing and stanza
ones.
* init/Makefile.am (init_SOURCES): Build and link parse_job.c and h
(TESTS): Run the parse job test suite
(test_cfgfile_SOURCES, test_cfgfile_LDFLAGS, test_cfgfile_LDADD):
Rename and update.
* init/parse_job.c: Rename all cfg_stanza_*() functions to just
stanza_*(), rename all cfg_parse_*() functions to just parse_*().
(parse_job, parse_process, stanza_exec, stanza_script, stanza_start)
(stanza_stop, stanza_emits, stanza_normal, stanza_env, stanza_limit):
Don't use NIH_MUST, it's fine to be out of memory and we should fail
in that case with a useful error. The user can always reload the
config file.
(cfg_read_job, cfg_watch_dir, cfg_job_name, cfg_create_modify_handler)
(cfg_delete_handler, cfg_visitor): Drop these functions for now.
* init/parse_job.h: Update so it just contains the one prototype.
* init/tests/test_parse_job.c: Update all tests to pass a string
to parse_job(), and check errors raised; rather than mucking around
with file descriptors all of the time. Spend the effort while we're
in here to run TEST_ALLOC_FAIL where we can.
* init/main.c: Drop config file loading for now since it's missing.
2007-05-27 Scott James Remnant <scott@netsplit.com>
* init/cfgfile.h (CFG_DIR): Drop this define, since it's in paths.h
(CfgDirectory):
* init/cfgfile.c (cfg_read_job): Separate out the job-handling code
into a new function that we could call from a stanza if we want
later; this one now just maps the file into memory and deals with
exceptions from the parsing.
(cfg_parse_job): Function containing the seperated out code; parses
a new job, marking it as a replacement for any existing job with the
same name. Drop the warnings for using pid options without a daemon,
since these are actually useful for other things later.
* init/tests/test_cfgfile.c (test_read_job): Drop the check on
unexpected daemon options, since we don't issue these warnings
anymore.
2007-05-20 Scott James Remnant <scott@netsplit.com>
* init/event.c (event_match): Change to accept Event as the first
argument and EventInfo as the second, making it obvious that this
matches a received Event against known EventInfo rather than just
comparing two info structs (since the order matters).
* init/event.h: Update prototype.
* init/tests/test_event.c (test_match): Update test accordingly.
(test_poll): Fix typo.
* init/job.c (job_handle_event): Pass in the event as the first
argument to event_match, rather than its info.
* TODO: Update.
* init/job.c (job_emit_event): Return the event that we emit; don't
bother tracking block status or setting blocked, leave that to the
state loop so things are more obvious.
(job_change_state): Set the blocked flag here for starting and stopping
to the return value of job_emit_event().
* init/event.c (event_ref, event_unref): Reference counting of events
so we don't free those we still need.
(event_block, event_unblock): Blocker counting that replaces the
previous jobs member.
(event_new): Initialise refs and blockers fields.
(event_emit_finished): Remove this function.
(event_poll): Handle the new done state, and deal with the blockers
and references counts; turns out that we can fall all the way through
this switch if these are zero without needing to check again.
(event_pending): Remove call to event_emit_finished, the event_poll()
loop handles this case now.
(event_finished): Set progress to done on the way out.
* init/event.h (EventProgress): Add new done state
(Event): Add refs and blockers members, replacing jobs
* init/tests/test_event.c (test_new): Check refs and blockers are
initialised to zero.
(test_ref, test_unref, test_block, test_unblock): Check the ref
counting function behaviours.
(test_emit_finished): Drop this function since it's not used
* init/job.c (job_change_cause): Reference and block the event,
and unblock and unreference before changing.
(job_emit_event): Reference the event that blocks the job from
continuing.
(job_handle_event_finished): Unreference the blocking event again.
(job_change_state): Make sure that blocked has been cleared before
allowing a state change.
* init/tests/test_job.c: Change tests to use refs/blockers on the
cause event when counting, and also to follow the status of blocked
since that is now ref-counted as well.
2007-05-18 Scott James Remnant <scott@netsplit.com>
* init/main.c (main, cad_handler, kbd_handler, pwr_handler): Use
event_new rather than event_emit.
* init/job.h (Job): Change type of cause and blocked to Event
* init/job.c (job_change_goal, job_change_cause, job_emit_event)
(job_handle_event, job_handle_event_finished): Update all references
to EventEmission to use Event instead.
(job_detect_stalled): Call event_new instead of event_emit
(job_run_process): Use the info member of cause, not event member
* init/tests/test_job.c (test_change_goal, test_change_state)
(test_run_process, test_child_reaper, test_handle_event)
(test_handle_event_finished): Update all references to EventEmission
to use Event instead.
(test_detect_stalled): Correct to use right structure types.
* init/process.c (process_setup_environment): Use cause's info member,
rather than event member.
* init/tests/test_process.c (test_spawn): Update to use Event.
* init/notify.h (NotifySubscription): Change member to event
* init/notify.c (notify_subscribe_event)
(notify_subscription_find, notify_job_event, notify_event)
(notify_event_finished): Update functions to use event member and
Event structures.
* init/tests/test_notify.c (test_subscribe_event)
(test_subscription_find, test_job, test_job_event, test_event)
(test_event_finished): Update to use Event instead of EventEmission
* init/control.c (control_event_emit): Update to use event_new.
* init/tests/test_control.c (test_event_emit)
(test_subscribe_events, test_unsubscribe_events): Update to use
Event rather than EventEmission.
* init/event.h: Fix up a few references.
* init/tests/test_event.c (test_new): Remove reference to emission.
* init/event.h (EventEmission): Rename to Event, and rename event
member to info.
* init/event.c (event_emit_next_id): Rename to event_next_id
(event_emit): Rename to event_new, and add standard parent argument.
(event_emit_find_by_id): Rename to event_find_by_id
(event_poll): Iterate over Events in the list
(event_pending, event_finished): Operate on Event
* init/tests/test_event.c (test_emit): Rename to test_new and
adjust for names and arguments.
(test_emit_find_by_id): Rename to test_find_by_id and adjust for
names.
(test_emit_finished, test_poll): Adjust names.
* init/cfgfile.c (cfg_stanza_start, cfg_stanza_stop)
(cfg_stanza_emits): Convert to use EventInfo and event_info_*.
* init/job.c (job_copy): Use EventInfo and event_info_copy.
(job_handle_event, job_detect_stalled): Iterate EventInfo structures
* init/tests/test_cfgfile.c (test_stanza_start, test_stanza_stop)
(test_stanza_emits): Update to use EventInfo
* init/tests/test_job.c (test_copy, test_handle_event)
(test_handle_event_finished, test_detect_stalled): Update to use
EventInfo and event_info_new
* init/event.c (event_copy): Use nih_str_array_copy here, to make the
code somewhat simpler.
(event_finished): Copy the arguments and environment from the old
event, rather than stealing and reparenting.
* init/job.c (job_copy): Use nih_str_array_copy here too.
(job_run_process): Use nih_str_array_append to add the arguments from
the emission onto the command run.
* init/event.h (Event): Rename to EventInfo, since this structure
representations information about an event, rather than an actual
event in progress.
* init/event.c (event_new): Rename to event_info_new, also now can
take arguments and environment like event_emit() can.
(event_copy): Rename to event_info_copy.
* init/tests/test_event.c (test_new): Rename to test_info_new,
update names in test and test being given args or env.
(test_copy): Rename to test_info_copy and update names in test.
(test_match, test_poll): Use EventInfo.
* TODO: Update.
2007-04-24 Scott James Remnant <scott@netsplit.com>
* configure.ac: Add AM_PROG_CC_C_O since we use per-target flags
for one of the test cases.
2007-03-16 Scott James Remnant <scott@netsplit.com>
* upstart/message.c (upstart_message_newv): Add va_end to match
va_copy because the standard says so.
* upstart/wire.c (upstart_push_packv, upstart_pop_packv): Add
va_end here as well.
2007-03-13 Scott James Remnant <scott@netsplit.com>
* init/main.c: Wait until we've closed inherited standard file
descriptors and opened the console instead before trying to open the
control socket; otherwise we end up closing it by accident if we
weren't opened with sufficient descriptors in the first place.
Also wait until we've set up the logger before trying to parse the
configuration. In fact both of these things need to be pretty low
down the main() function.
* init/tests/test_job.c (test_run_process): Skip /dev/fd test cases
if that's not available.
* init/tests/test_control.c (test_log_priority): Make sure we know
that the message has been sent before calling the watcher.
* init/cfgfile.c (cfg_watch_dir): We get ENOSYS for missing inotify
support, not EOPNOTSUPP.
* init/tests/test_cfgfile.c (test_watch_dir): Actually make the
directory tree before testing for inotify, since we use the same
tree there too.
* util/initctl.c (job_info_output): Restructure so gcc doesn't think
name can be used uninitialised.
* init/tests/test_cfgfile.c (test_watch_dir): Correct an error where
i wouldn't be initialised if we skipped the inotify tests.
* util/initctl.c (job_info_output): Restructure so gcc doesn't think
* init/process.c (process_setup_environment): job id fits inside
a %u now
* upstart/message.h: Style; always refer to "unsigned int" as
"unsigned int", and never "unsigned.
* upstart/tests/test_message.c (my_handler): Catch a stray couple
of "unsigned"s
* init/control.c (control_job_query, control_job_start)
(control_job_stop): Change type of id argument to unsigned int,
and call printf with %u to output it.
* init/tests/test_control.c (check_job, check_job_instance)
(check_job_instance_end, check_job_status__waiting)
(check_job_status_end__waiting, check_job_status__starting)
(check_job_status_end__starting, check_job_status__running)
(check_job_status_end__running, check_job_status__pre_stop)
(check_job_status_end__pre_stop, check_job_status__stopping)
(check_job_status_end__stopping, check_job_status__deleted)
(check_job_status_end__deleted, check_job_unknown)
(check_job_invalid, check_job_unchanged, check_event): Change
type of id arguments to unsigned int.
(check_list): Change type of id to unsigned int.
* init/tests/test_notify.c (check_job_status)
(check_job_status_end, check_job_finished, check_event)
(check_event_caused, check_event_finished): Change type of id
arguments to unsigned int.
* init/job.h (Job): Change the type of the id to unsigned int.
* init/job.c (job_next_id): Change ids to be unsigned ints, and now
we can just use %u in the nih_error call.
(job_find_by_id): Change argument to be unsigned int
* init/tests/test_job.c (test_find_by_id): Change id type to unsigned
int.
* init/event.h (Event): Change the type of the id to unsigned int.
* init/event.c (event_emit_next_id): Change ids to be unsigned ints,
and now we can just use %u in the nih_error call.
(event_emit_find_by_id): Change argument to be unsigned int
* init/tests/test_event.c (test_emit, test_emit_find_by_id)
(check_event, check_event_finished): Change id type to unsigned int.
* util/initctl.c (output_name): Use an unsigned int for the job id,
which means we can use ordinary %u for the printf argument.
(handle_job, handle_job_finished, handle_job_instance)
(handle_job_instance_end, handle_job_status)
(handle_job_status_end, handle_job_unknown, handle_job_invalid)
(handle_job_unchanged, handle_event, handle_event_caused)
(handle_event_finished): Change argument type of id from uint32_t
to unsigned int.
(job_info_output): Change output type of id from %zu to %u
* upstart/message.c (upstart_message_handle): Use unsigned int for
ids, rather than a fixed-width type.
* upstart/tests/test_message.c (my_handler): Use unsigned int for
the ids, and give "unsigned int" instead of "unsigned" to va_arg as
a matter of style.
* upstart/wire.c (upstart_push_int, upstart_pop_int): Send over the
wire using a plain old integer type, instead of a fixed width type;
there's no advantage to using the fixed-width type and we could hurt
ourselves if we tried running on ILP64.
(upstart_push_unsigned, upstart_pop_unsigned): Likewise use a plain
unsigned int over the wire.
(upstart_push_string, upstart_pop_string): Use an unsigned int for
the length of the string, technically this means that we silently
truncate any string that's greater than 4GB on 64-bit platforms;
it's either that or make the test cases harder (we did this before
anyway).
(upstart_push_header, upstart_pop_header): Type is always an unsigned
int (best conversion from an enum)
2007-03-11 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.3.9
* NEWS: Update.
* util/man/initctl.8: Document the new commands.
* TODO: Update.
* init/job.c (job_handle_event): Correct the function so we don't
try and stop the master of an instance, and cause an assertion error.
* util/initctl.c: Oops, correct function pointers in command table
* util/tests/test_initctl.c (test_version_action):
* util/initctl.c (handle_version): Handle receipt of the version
reply.
(version_action): Send the version-query message to the server and
expect one response.
(log_priority_action): Parse the single argument into an NihLogLevel
and send it to the server.
* init/control.c (control_version_query, control_log_priority):
Functions to handle the new messages from the server pov
* init/tests/test_control.c (test_version_query)
(test_log_priority): Test the new messages are handled properly.
(check_version): Check the version string matches.
* upstart/message.h: Add messages for querying the version of the
init daemon and changing the log priority.
* upstart/message.c (upstart_message_newv)
(upstart_message_handle): Marshal the new messages.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Test the marshalling of the new messages,
* upstart/libupstart.ver: Add enum functions to the global list.
* util/initctl.c (start_action, stop_action): Imply --no-wait if
we take the job id or name from an environment variable, since we'd
end up waiting for ourselves otherwise
* util/tests/test_initctl.c (test_start_action, test_stop_action):
Update test cases to make sure no-wait is implied.
2007-03-09 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.3.8
* NEWS: Updated.
* configure.ac: Increase version to 0.3.7
* init/tests/test_job.c (test_change_state): Add a test case for
deleting the last instance of a replaced job.
* init/job.c (job_change_state): When moving a instance of a job into
the deleted state, check whether we should replace the job it's an
instance of, and if so, change that job's state too.
* TODO: Update.
* util/initctl.c (handle_job_list): Always allocate current_list,
since we need it to be the parent of pointers we attach to it.
(handle_job_list_end): Always free the current list, only suppress
output if there aren't any entries in it.
(initctl_recv): Check the current_list pointer, no need for in_list
(handle_job_instance, handle_job_instance_end, handle_job_status):
Check current_list not in_list.
* util/tests/test_initctl.c: Correct some memory leaks.
* init/process.c (process_setup_environment): Set the UPSTART_JOB_ID
environment variable to the job's unique id.
* init/tests/test_process.c (test_spawn): Make sure it's set.
* util/man/initctl.8: Update the initctl manpage.
* compat/sysv/man/reboot.8: Correct a minor grammar error.
* compat/sysv/man/shutdown.8: Fix reference from runlevel to telinit.
* README: Add a README that copies the text from the web page and
adds some notes about recommended operating system versions.
* util/initctl.c: Completely rewrite initctl, top to bottom; handling
of the new messages is done natively, meaning that the commands just
vary the requests send and number of responses expected.
* util/tests/test_initctl.c: Test all of the new code.
* init/main.c: Improve restarting and rescuing a little; store the
program path in a static variable so we can always access it, and
use the exported loglevel to pass the same to the new process.
* TODO: Update.
* compat/sysv/shutdown.c: More error/fatal adjustments.
* compat/sysv/telinit.c: More error/fatal adjustments.
2007-03-08 Scott James Remnant <scott@netsplit.com>
* init/main.c (main, crash_handler): Promote deadly errors to nih_fatal
* logd/main.c (main): Promote deadly errors to nih_fatal
* compat/sysv/reboot.c (main): Promote deadly errors to nih_fatal
* compat/sysv/shutdown.c (main, shutdown_now): Promote deadly errors
to nih_fatal
* compat/sysv/telinit.c (main): Promote deadly errors to nih_fatal
* init/event.c (event_pending): The message that we're handling an
event should be logged with --verbose.
* init/cfgfile.c (cfg_parse_script): Remove the unnecessary check for
a token inside a script block.
* TODO: Update.
* init/control.c (control_watch_jobs): Rename to control_subscribe_jobs
and update to handle new event name.
(control_unwatch_jobs): Rename to control_unsubscribe_jobs and update
to handle the new event name.
(control_watch_events): Rename to control_subscribe_events and update
to handle the new event name.
(control_unwatch_events): Rename to control_unsubscribe_events and
update to handle the new event name.
* init/tests/test_control.c (test_watch_jobs): Rename to
test_subscribe_jobs and update to new event name.
(test_unwatch_jobs): Rename to test_unsubscribe_jobs and update to
new event name.
(test_watch_events): Rename to test_subscribe_events and update to
new event name.
(test_unwatch_events): Rename to test_unsubscribe events and update
to new event name.
* upstart/message.h: Rename the watch commands to subscribe/unsubscribe
and regroup with new message numbers.
* upstart/message.c (upstart_message_newv)
(upstart_message_handle): Marshal the updated subscription messages.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Update tests to new names and numbers.
* TODO: Update.
* upstart/message.c (upstart_message_handle): Raise a the unknown
message error if the type is unknown, rather than the invalid message
error.
* upstart/tests/test_message.c (test_handle): Correct test case.
* init/job.c (job_change_state): Correct a problem here too, when
moving from pre-stop to running, we don't want to emit a started event
since we never emitted a stopping event and never killed the process
anyway. We do need to notify the job as finished, since the process
that tried to stop it will need to be told not to wait any longer.
* init/tests/test_job.c (test_change_state): Add a test for pre-stop
back to running.
* doc/states.dot: Fix an error in the state diagram; when moving from
starting back to waiting, due to a failed respawn, we need to emit
the stopped event otherwise it will never happen.
* doc/states.png: Update.
2007-03-05 Scott James Remnant <scott@netsplit.com>
* upstart/message.c (upstart_message_new): Make this a wrapper around
(upstart_message_newv): which has all the old code, but accepts a
va_list instead of making its own.
* upstart/message.h: Add prototype.
* init/main.c (crash_handler): Simply trying to leave a SEGV handler
doesn't work so well, we end up repeating the problem instruction.
We really can't resume from this point, and can't even jump elsewhere
since our state is probably buggered up. Only thing for it is to
re-exec ourselves with a clean state.
* init/cfgfile.c (cfg_read_job, cfg_delete_handler): Don't try and
free the magic (void *)-1 replacement (delete).
* util/events.c, util/events.c, util/jobs.c, util/jobs.h: With the
new message responses, that intermix event and job information freely,
it no longer makes sense to distinguish between them. So fold these
files back into the main initctl.c
* util/initctl.h: Drop unused header.
* util/Makefile.am (initctl_SOURCES): Update sources list.
(TESTS): Change which tests we build
(test_initctl_SOURCES, test_initctl_CFLAGS, test_initctl_LDFLAGS)
(test_initctl_LDADD): Build the new combined test case binary, use
an automake feature to rebuild initctl.c with -DTEST and a different
.o file, and thus be able to define out main()
* util/tests/test_events.c, util/tests/test_jobs.c: Collapse the two
test case files into one single
* util/tests/test_initctl.c
* init/control.c (control_job_find): And implement the find function
that returns a list of jobs matching an optional pattern.
* init/tests/test_control.c: Make sure we do send all messages.
(check_list): Complex function to check the responses to a job list
(test_job_find): Test a couple of job lists.
* init/tests/test_notify.c: Make sure we do send all messages.
* init/control.c (control_job_query): Implement the query message,
this just needs to return the status or instance set.
* init/tests/test_control.c (test_job_query): Test the query command.
(check_job_status__deleted, check_job_status_end__deleted): Pair of
functions to check we can query deleted jobs directly.
* init/control.c (control_send_instance): Function to send an instance
job, collating all of its instances together.
* init/control.h: Update.
* init/tests/test_control.c (test_send_instance): Check we receive
the right messages.
(check_job_instance, check_job_instance_end): Pair of functions to
check the instance messages.
* upstart/message.h: Add new UPSTART_JOB_INSTANCE and
UPSTART_JOB_INSTANCE_END messages which we'll use to communicate that
a job is an instance, and group the instances of it together.
* upstart/message.c (upstart_message_new, upstart_message_handle):
Marshal the new instance messages.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Test the new message types.
* upstart/message.h: Restore arguments to JOB_LIST, but rename to
pattern since that's what it is.
* upstart/message.c (upstart_message_handle): Restore arguments
with updated name.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Restore tests for arguments, rename and make sure we
include a wildcard.
2007-03-04 Scott James Remnant <scott@netsplit.com>
* upstart/message.h: Drop arguments to JOB_LIST.
* upstart/message.c (upstart_message_new, upstart_message_handle):
Drop arguments to JOB_LIST.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Drop the arguments from the test.
* init/control.c (control_job_start): Update to return INVALID for
instances and replacements; add the forgotten UPSTART_JOB message.
(control_job_stop): Update to return INVALID for replacements; add
the forgotten UPSTART_JOB message. Deal with instance masters
magically by iterating all instances and stopping those instead.
* init/tests/test_control.c (check_job_deleted): Rename to
check_job_invalid and check that message.
(check_job): Function to check the job we've acted upon.
(test_job_start): Check that we get the UPSTART_JOB message first,
restore the check on deleted jobs causing an error and add checks
that instance and replacement jobs also cause an error.
(test_job_stop): Check that we get the UPSTART_JOB message first,
restore the check on deleted jobs causing an error. Make sure
instances are handled.
* upstart/message.h: More message changes; add a JOB_FIND message
and replace UPSTART_JOB_DELETED with UPSTART_JOB_INVALID since there's
a few more problem conditions.
* upstart/message.c (upstart_message_new, upstart_message_handle):
Marshal the new message and update names.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Update tests to check the new message and update the
values and names of the existing ones.
* init/job.h (Job): Remove the delete flag, add replacement and
replacement_for pointers instead.
* init/job.c (job_new): Initialise replacement and replacement_for
pointers to NULL.
(job_find_by_name): Update to return what job the one we found is
a replacement for, and to skip DELETED jobs.
(job_instance): Make it simply illegal to call this for deleted jobs,
instances or replacements.
(job_change_goal): Make it illegal to change the goal of a replacement
job.
(job_free_deleted): Remove the previous code to handle deleted instance
masters, because it's now bogus.
(job_should_replace): New function to determine whether a job is
replaceable.
* init/tests/test_job.c (test_new): Check pointers are set.
(test_copy): Check that replacement and replacement_for are not
copied, since their state of an individual job.
(test_find_by_name): Update tests to make sure we ignore deleted jobs,
instances and replacements.
(test_instance): Remove test that will now cause an assertion,
and no longer check delete is set.
(test_change_goal): Remove test that will now cause an assertion.
(test_free_deleted): Remove test cases for deleted masters.
(test_should_replace): Test the new check function.
(test_change_state): Make sure that we end up in deleted for instances
and replaced jobs, and that replacements become the real job.
* init/cfgfile.c (cfg_read_job): Update to handle replacement jobs;
the old job's previous replacement is discarded, and set to the
current job; and then if the job should be replaced, it's moved
to deleted (which should promote the new job).
(cfg_delete_handler): Handle deletion of a job in a similar manner,
except we sent the replacement pointer to the special -1 value since
we have no actual replacement.
* init/tests/test_cfgfile.c (test_watch_dir): Update tests to make
sure that deletion and modification are handled wrt replacement.
(test_read_job): Make sure that reparsing an existing file is handled.
* init/tests/test_control.c (test_job_start): Remove checks that
delete gets set to true for instances.
(test_job_stop, test_job_start): Temporarily comment out deleted
job behaviour, since that's been somewhat changed.
* upstart/message.h: We're not going to return JOB_LIST for JOB_STOP
since that's just awkward for the client; just act on the master,
and return JOB_UNCHANGED.
* init/notify.c (notify_job_status): Move this function to
* init/control.c (control_send_job_status): here, since we need it for
the new control responses.
(control_job_query): New single function to list all jobs or a
particular job.
* init/control.h: Add prototype.
* init/tests/test_control.c (test_error_handler): Simplify this a
little to just sending a NO_OP message, since we can send an entire
stream of messages and leave them in the queue.
(check_job_status__stopping, check_job_process)
(check_job_status_end__stopping): Trio of check functions for a job
status that's stopping, with an active main process.
(test_send_job_status): Test the now global status function.
(check_job_status__starting, check_job_status_end__starting): Pair
of check functions for a starting job with no process yet.
(test_watch_jobs, test_unwatch_jobs): Update to expect the full new
job status messages, with an optional process part as well.
(check_event): Function to check an event.
(test_watch_events): Minor update to use above function.
(check_job_status__waiting, check_job_status_end__waiting): Pair of
check functions for the first step in starting a job (goal change only)
(check_job_unknown, check_job_deleted, check_job_unchanged): Trio
of functions to check common error responses.
(test_job_start): Update tests to newer behaviour.
(check_job_status__running, check_job_status_end__running)
(check_job_status__pre_stop, check_job_status_end__pre_stop): Checks
for the states we go through when stopping a job.
(test_job_stop): Update tests to newer behaviour.
* init/notify.c (notify_job, notify_job_event, notify_job_finished):
Update to call the newly exported function.
* init/job.c: Make job_id and job_id_wrapped externally available.
* init/job.h: Update.
* init/event.c: Make emission_id and emission_id_wrapped externally
available.
* init/event.h: Update.
* upstart/message.h: Rename UPSTART_JOB_INVALID to
UPSTART_JOB_UNCHANGED, as it's not really invalid just a no-op
* upstart/message.c (upstart_message_new, upstart_message_handle):
Update the constant, fields are unchanged,
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Rename constants/messages.
* upstart/message.h: Turns out we need extra errors to indicate that
the job was deleted or already at that goal, otherwise the client
would sit there waiting for the finished event.
* upstart/message.c (upstart_message_new, upstart_message_handle):
Marshal the new error messages.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Test the handling of the new messages.
* init/tests/test_job.c (test_free_deleted): Found a bug; because
master instances never change state, they never end up in the deleted
state so are never reaped. Add some test cases for cleaning them up,
but not while they have remaining instances.
* init/job.c (job_free_deleted): Implement the bug fix.
* init/job.c (job_instance): Split out the instance spawning code
into its own function, as we'll frequently need a pointer to the
instance before we try and change the goal.
(job_change_goal): Clean this function back up again, it no longer
needs to return values and can assert that it's never called for
deleted jobs or instance mastersr.
(job_handle_event): Spawn an instance when we get a start event.
* init/job.h: Update.
* init/tests/test_job.c (test_instance): Check instance creation.
(test_change_goal): Update tests now that it doesn't return a value
again, and doesn't spawn instances itself.
(test_handle_event): Make sure instances are spawned.
* init/tests/test_event.c (test_poll): Needs a slight fix now that
we generate more events than we check, and that subscriptions go
away automatically.
* init/notify.c (notify_job_status): Static function to handle
sending the more complicated job status message series
(notify_job): Call notify_job_status() to send the new-style message
(notify_job_event): Send the new UPSTART_EVENT_CAUSED message with
the emission id, then call notify_job_status() to send the new-style
common status message.
(notify_job_finished): New function to be called when we reach the
job rest state, notifies and unsubscribes directly subscribed
processes, and includes failed information.
(notify_event_finished): Unsubscribe processes after sending the
finished event, since the event has gone away. Also don't send
this to processes subscribed to all events, since it's not useful
for them.
* init/notify.h: Add prototype.
* init/tests/test_notify.c: Update all test cases and helper
functions to the new message types.
(test_job_finished): Check the new finished message is sent with
a status message preceeding it.
* init/job.c (job_change_state, job_change_state): Notify subscribed
processes with notify_job_finished() when in the running (for service)
or waiting states, just before we drop the cause.
* upstart/message.h: Add failed, failed_process and exit_status
arguments to UPSTART_JOB_FINISHED.
* upstart/message.c (upstart_message_new, upstart_message_handle):
Marshal the new arguments.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Test the new arguments.
* upstart/message.h: Update the message types, introducing a more
structured job message set and replacing the UPSTART_EVENT_JOB_STATUS
message with UPSTART_EVENT_CAUSED which will be immediately followed
by an ordinary UPSTART_JOB_STATUS message.
* upstart/message.c (upstart_message_new, upstart_message_handle):
Marshal the new messages.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Test the new message types.
* TODO: Update.
2007-03-03 Scott James Remnant <scott@netsplit.com>
* TODO: Update.
* init/cfgfile.c (cfg_parse_exec, cfg_parse_script): Separate out
the parsing of an exec or script stanza into separate functions,
seeing as this is quite a common operation. This also means we
just need to change them in one place now.
(cfg_parse_process): Function to call either of the above depending
on the next argument.
(cfg_stanza_exec): Call cfg_parse_exec instead.
(cfg_stanza_script): Call cfg_parse_script instead.
(cfg_stanza_pre_start, cfg_stanza_post_start)
(cfg_stanza_pre_stop, cfg_stanza_post_stop): Call cfg_parse_process
with the right arguments instead of doing by hand in each function.
* init/event.c (event_emit_next_id): Split the id assigning code into
a static inline function for easier modification.
* init/job.c (job_next_id): Use the same style function here too.
2007-03-02 Scott James Remnant <scott@netsplit.com>
* init/event.c (event_emit): Port the slightly more efficient in the
early case code from job_new.
* init/job.h (Job): Add a unique id to the job structure.
* init/job.c (job_new): Assign an incrementing id to each new job
allocated.
(job_find_by_id): Locate a job by its unique id, sadly not very
efficient in a hash table ;-)
(job_name): New hash key function since name isn't the first entry
anymore.
(job_init): Change hash key function.
* init/tests/test_job.c (test_find_by_id): Make sure we can find a
job by its id.
* init/job.c (job_change_goal): Return the new instance in that
circumstance, and clean up a little bit.
* init/job.h: Update prototype.
* init/tests/test_job.c (test_change_goal): Update tests.
* init/job.c (job_find_by_name): Skip jobs marked for deletion too.
* init/tests/test_job.c (test_find_by_name): Update test case.
* init/event.h, init/notify.h, upstart/message.h: Provide C-level names
for enums, this makes the compiler generate things that gdb can get.
* init/job.c (job_run_process, job_kill_process, job_kill_timer):
Change process argument to be a plain ProcessType, this means we
know exactly which process we're trying to run or kill.
(job_change_state): Update calls to job_run_process
and job_kill_process
* init/tests/test_job.c (test_run_process, test_kill_process): Update
function calls to just pass a ProcessType in.
* upstart/enum.h: Rename JobAction to ProcessType.
* upstart/enum.c (job_action_name): Rename to process_name.
(job_action_from_name): Rename to process_from_name.
* upstart/tests/test_enum.c (test_action_name, test_action_from_name):
Rename and update to match.
* init/job.c (job_new, job_copy, job_change_state)
(job_next_state): Change JOB_*_ACTION constants to PROCESS_*.
(job_find_by_pid): Change JobAction argument to ProcessType.
(job_emit_event): Call process_name on the failed process.
(job_child_reaper): Update to use ProcessType instead of JobAction.
* init/job.h (Job): Change type of failed_process to ProcessType.
* init/tests/test_job.c (test_find_by_pid): Update to use ProcessType
instead of JobAction in tests.
(test_new, test_copy, test_change_goal, test_change_state)
(test_next_state, test_run_process, test_kill_process)
(test_child_reaper, test_handle_event_finished): Change JOB_*_ACTION
constants to PROCESS_*
* init/cfgfile.c (cfg_stanza_exec, cfg_stanza_script)
(cfg_stanza_pre_start, cfg_stanza_post_start)
(cfg_stanza_pre_stop, cfg_stanza_post_stop): Change JOB_*_ACTION
constants to PROCESS_*
* init/tests/test_cfgfile.c (test_stanza_exec)
(test_stanza_script, test_stanza_pre_start)
(test_stanza_post_start, test_stanza_pre_stop)
(test_stanza_post_stop, test_read_job, test_watch_dir): Change
JOB_*_ACTION constants to PROCESS_*
* init/tests/test_event.c (test_poll): Change JOB_*_ACTION constants
to PROCESS_*
* init/tests/test_control.c (test_job_start, test_job_stop): Change
JOB_*_ACTION constants to PROCESS_*
* init/cfgfile.c (cfg_watch_dir): Restore the prefix argument; pass
as the data pointer to the inotify callbacks and visitor function.
Change the return value to be the watch structure.
(cfg_job_name): Add prefix argument and prepend to relative path.
(cfg_create_modify_handler, cfg_delete_handler, cfg_visitor): Get
the prefix for the job names from the data pointer and pass to
cfg_job_name().
* init/cfgfile.h: Update prototypes.
* init/tests/test_cfgfile.c (test_watch_dir): Actually test the
watch functions.
* init/main.c (main): Pass NULL for the prefix for the global job
directory, compare the return value against (void *)-1.
* TODO: Update.
* init/cfgfile.c (cfg_stanza_on): Drop the simple on stanza.
* init/tests/test_cfgfile.c (test_stanza_on): Remove test case.
* TODO: Update.
2007-03-01 Scott James Remnant <scott@netsplit.com>
* util/jobs.c (handle_job_status): Drop the process field from the
output for now.
* util/events.c (handle_event_job_status): Likewise
* util/tests/test_jobs.c (test_start_action, test_list_action)
(test_jobs_action): Drop pid from messages we simulate.
* util/tests/test_events.c (test_emit_action): Likewise.
* upstart/message.c (upstart_message_new, upstart_message_handle):
Remove the pid field from the job status and event job status
messages.
* upstart/message.h: Update description of job status and event
job status message to remove the pid field.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Remove checks using the pid field.
* init/control.c (control_job_start, control_job_stop)
(control_job_query, control_job_list): Remove the pid field from
the messages, it'll come back later when we get better message
formats.
* init/tests/test_control.c (check_job_status, check_job_waiting)
(check_job_started, check_job_stopped): Remove checks on the process
id, since that field is gone from the message.
(test_job_stop): Use the pid field of the main process.
(test_job_start): Initialise the main action process.
* init/notify.c (notify_job, notify_job_event): Remove the pid field
from the message, it'll come back later when we get better message
formats.
* init/tests/test_notify.c (check_job_status)
(check_event_job_status): Remove checks on the pid, since that field
is no longer present.
* init/job.c (job_process_copy): Use job_process_new here, oops.
* init/cfgfile.c (cfg_stanza_exec, cfg_stanza_script)
(cfg_stanza_pre_start, cfg_stanza_post_start)
(cfg_stanza_pre_stop, cfg_stanza_post_stop): Use job_process_new
to allocate process structures and store in the process array.
* init/tests/test_cfgfile.c (test_read_job, test_stanza_exec)
(test_stanza_script, test_stanza_pre_start)
(test_stanza_post_start, test_stanza_pre_stop)
(test_stanza_post_stop): Update test cases to use process array
member information.
* init/tests/test_event.c (test_poll): Update to use newer job process
array and find the pid under there.
* init/job.h (Job): Remove the pid and aux_pid fields; replace the
individual JobProcess pointers with an array of them of a fixed
minimum size; replace failed_state with failed_process.
(JobProcess): add a pid field here, so now we can obtain the pid on
an individual process/action basis rather than global.
* init/job.c (job_process_new): Function to create a JobProcess
structure, setting the initial values to FALSE/NULL/0.
(job_process_copy): Function to copy a JobProcess.
(job_new): Don't initialise the pid or aux_pid members, initialise
the process array to a fixed initial size and set the members to NULL,
initialise the failed_process member to -1.
(job_copy): Update to use job_process_copy and copy the process array.
(job_find_by_pid): Look through the process structures in the job's
process array to find the pid, and optionally return which action it
was.
(job_change_state): Call job_kill_process in the JOB_KILLED state if
we have a main process and that has a pid, pass in the main process.
(job_next_state): Check the process id of the main process when
deciding what the next state is for running.
(job_run_process): Store the process id in the process structure
(job_kill_process): Accept a process structure and use that to obtain
the process id we need to send TERM too. Remove the code that forced
a state change if kill() failed, since we will get a child signal
anyway and should do it there.
(job_kill_timer): Likewise, accept a process structure and don't
forcibly change the state anymore.
(job_child_reaper): Rewrite to switch based on the action that died,
rather than the state we were in; assert that the state is what we
expected.
(job_emit_event): The argument to the failed event is now the action
name, rather than the state name; an action of -1 indicates that
respawn failed.
* init/tests/test_job.c (test_process_new, test_process_copy): Make
sure the structure is created and copied properly.
(test_new, test_copy): Drop checks on the pid and aux_pid members,
add checks for the process array and pid members of processes.
(test_find_by_pid): Update test case to make sure we can find the pid
of any process, returning the action index rather than the process
pointer.
(test_run_process, test_kill_process, test_change_goal)
(test_change_state, test_next_state, test_child_reaper): Update test
cases to use pid fields inside process structures rather than the
pid or aux_pid members.
(test_handle_event, test_handle_event_finished)
(test_free_deleted): Update to avoid pid field checks.
* upstart/enum.h (JobAction): Enumeration of different actions.
* upstart/enum.c (job_action_name, job_action_from_name): Enumeration
to string conversion functions.
* upstart/tests/test_enum.c (test_action_name)
(test_action_from_name): Tests for the new functions.
* init/cfgfile.c (cfg_read_job): Instead of trying to copy over an
old job's state and instances into the new one, mark the old job
as deleted. This ensures we never end up applying a new post-stop
script to a job started with an old pre-start script, etc. It also
makes life so much simpler.
* init/tests/test_cfgfile.c (test_read_job): Update tests to make
sure the old job is marked for deletion, instead of freed.
* TODO: Update.
* init/notify.c (notify_job): Split out notification to processes
subscribed to the cause event into a new function
(notify_job_event): We can call this when we change cause.
* init/job.c (job_change_state): Notify anyone subscribed to the
job after we've changed the state, rather than before, otherwise
we won't know the new pids or anything.
(job_change_cause): Call notify_job_event before changing the cause
so that subscribers get a final status update.
* init/tests/test_notify.c (test_job_event): Check the new function.
* TODO: Update.
* init/cfgfile.c (cfg_stanza_respawn): Remove the shortcut that
lets you specify "respawn COMMAND". It was confusing as it hid
the common "[when] exec"/"[when] script" syntax, made it non-obvious
that "exec" and "respawn" were the same flag, etc.
* init/tests/test_cfgfile.c (test_stanza_respawn): Update tests.
(test_stanza_service): Fix test case to not use shortcut.
* logd/event.d/logd.in: Update to not use respawn shortcut.
2007-02-25 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_child_reaper): Shift the signal value into the
higher byte to make it easier to detect, and not stamp over exit
statuses between 128 and 255.
(job_emit_event): Detect the signal stored in the new way.
* init/cfgfile.c (cfg_stanza_normal): Store signal in the higher bytes.
* init/tests/test_job.c (test_copy, test_change_state)
(test_child_reaper): Update test cases.
* init/tests/test_cfgfile.c (test_stanza_normal): Update test.
* TODO: Update.
* init/event.h (PWRSTATUS_EVENT): Add new power-status-changed event.
* init/main.c (pwd_handler): Handle the SIGPWR signal by generating
the new event, leave it up to a job to parse the file and do
whatever it likes.
* TODO: Update.
2007-02-13 Scott James Remnant <scott@netsplit.com>
* upstart/tests/test_message.c (test_reader, test_handle_using)
(test_handle); Usual fix for gcc optimiser thinking that fixed
for loops might not be.
* init/tests/test_job.c (test_run_process, test_kill_process):
Likewise.
* init/tests/test_notify.c (test_subscription_find): I still don't
know what a type-punned pointer is, nor why dereferencing such a
thing would break strict-aliasing rules.
* init/tests/test_cfgfile.c (test_read_job): More type-punning.
* util/tests/test_jobs.c (test_start_action): More for-loop action.
* util/tests/test_events.c (test_emit_action): And again.
2007-02-11 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_change_goal): We need to be able to stop a running
job without a process, because that's what a job-as-state is! The
check was added because job_child_reaper calls job_change_goal and
then job_change_state immediately after, we should fix that instead.
(job_child_reaper): If we call job_change_goal while in the running
state, it will call job_change_state for us; so check for that first
and don't change the state!
* init/tests/test_job.c (test_change_goal): Update the test to ensure
that we can stop a job with no running process.
* init/cfgfile.c (cfg_stanza_normalexit): normalexit is inconsistent,
change to "normal exit"
* init/tests/test_cfgfile.c (test_stanza_normalexit): Update.
* init/cfgfile.c (cfg_stanza_start, cfg_stanza_stop)
(cfg_stanza_pre_start, cfg_stanza_post_start)
(cfg_stanza_pre_stop, cfg_stanza_post_stop, cfg_stanza_respawn):
We're not going to allow stanza keywords to be quoted, since this
gives us an easy way to allow users to make something explicitly
not a keyword.
2007-02-10 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.3.6
* configure.ac: Increase version to 0.3.5
* NEWS: Update.
* TODO: Update.
* TODO: More notes.
* TODO: Note an issue with using JobProcess->pid
* init/cfgfile.c (cfg_stanza_pre_start, cfg_stanza_post_start)
(cfg_stanza_pre_stop, cfg_stanza_post_stop): Add a needed check
for a token when parsing "exec". Correct line number we expect
to see the duplicated value on. Correct expected error for missing
argument from "Unexpected token" to "Expected token".
* init/tests/test_cfgfile.c (main): Actually invoke the tests for
the scripts.
* init/cfgfile.c (cfg_read_job): Correct type of lineno in error.
* TOOD: Minor notify bug
* TODO: Big update.
* init/tests/test_job.c (test_child_reaper): Make sure that we can
reap post-start and pre-stop processes, and have only the aux_pid
changed. Also make sure that if the running process dies while
in these states, with or without an aux process, that we don't
transition badly.
* init/job.c (job_find_by_pid): Check aux_pid as well.
* init/tests/test_job.c (test_find_by_pid): Make sure we can find it.
* init/job.h (Job): Add an auxiliary pid member.
* init/job.c (job_new): Initialise the aux_pid member.
(job_change_state): Run the post-start and pre-stop scripts when we
enter the state with the same name (assuming they exist).
(job_run_process): Store the pid in aux_pid when starting the
post-start or pre-stop processes.
* init/tests/test_job.c (test_change_state): Add tests for running
the new post-start and pre-stop scripts; which get their process ids
stored in aux_pid instead of pid.
(test_new): Make sure the aux_pid member is initialised properly.
(test_copy): Make sure the aux_pid member is not copied.
* TODO: Update.
* init/tests/test_job.c (test_change_state): Add a check for the
daemon stanza holding the job in spawned; we snuck this in a while
back and never tested it (there's no support to get it out of
spawned yet).
* init/job.h (Job): Add new post_start and pre_stop scripts.
* init/job.c (job_new): Initialise new scripts to NULL.
(job_copy): Copy the information from the new scripts over as well.
* init/tests/test_job.c (test_new): Check they're initialised.
(test_copy): Check that the information is copied properly.
* init/cfgfile.c (cfg_stanza_post_start, cfg_stanza_pre_stop): Add
new script stanza functions for the additional two scripts that
we want.
* init/tests/test_cfgfile.c (test_stanza_post_start)
(test_stanza_pre_stop): Add tests for the new stanzas.
* init/cfgfile.c (cfg_stanza_exec, cfg_stanza_script): Rewrite to
allocate a JobProcess and parse the command or script into it.
(cfg_read_job): Fix the long broken assumption that pid_file and
pid_binary are required for respawn, when they're actually required
for daemon.
(cfg_stanza_start, cfg_stanza_stop): Remove script second-level.
(cfg_stanza_respawn): Parse into the job's process.
(cfg_stanza_pre_start, cfg_stanza_post_stop): New stanzas for the
processes alone.
* init/tests/test_cfgfile.c (test_read_job): Update a few test
cases to match reality.
(test_stanza_start, test_stanza_stop): Remove script-related checks.
2007-02-09 Scott James Remnant <scott@netsplit.com>
* init/tests/test_job.c (test_kill_process): Poll the event queue
after each test to get rid of the allocated events and make valgrind
happy.
* init/tests/test_control.c (test_job_start, test_job_stop)
(test_event_emit): Poll the event queue after each test to get rid
of the allocated events, as they make valgrind complain.
(test_event_emit): Free args and env when done.
* init/job.h (JobName): Drop obsolete structure
(JobProcess): Add a new structure to represent a single process
within the job, instead of using two variables to pick either the
script or command.
(Job): Change command and script to a single JobProcess called process;
change start_script and stop_script to a JobProcess called pre_start
and post_stop respectively.
* init/job.c (job_new): Initialise new members to NULL.
(job_copy): Copy the process structures across, including contents.
(job_change_state): Call job_run_process passing in the structure;
rather than fiddling with if statements.
(job_run_script, job_run_command, job_run_process): Combine all of
these three functions into a single new job_run_process function.
* init/tests/test_job.c (test_new, test_copy, test_change_goal)
(test_change_state, test_child_reaper)
(test_handle_event_finished): Change to using JobProcess for when
we need to construct a command.
(test_run_script, test_run_command): Merge into single new
(test_run_process) function.
* init/tests/test_event.c (test_poll): Replace command with process.
* init/tests/test_control.c (test_job_start): Change to using
JobProcess to specify the command.
* init/main.c (main): Run job_free_deleted each time through the
main loop.
* init/job.c (job_change_goal): Minor tweak to the logic; we may
have just made the job an instance, that should still let us stop
the one underneath.
* TODO: Update.
* util/jobs.c (do_job): Always expect a list of replies.
* init/control.c (control_job_status, control_job_stop)
(control_job_query): Reply with information about all instances of
the job.
* init/tests/test_control.c (test_job_status, test_job_stop)
(test_job_query): Make sure we get the list end even for a single job;
and make sure we get details of all instances attached to the job.
* init/tests/test_job.c (test_change_goal): Check that starting
an instance job actually starts a new instance of it.
* init/cfgfile.c (cfg_stanza_limit): Support the word "unlimited" in
limit arguments for both the soft and hard values.
* init/tests/test_cfgfile.c (test_stanza_limit): Make sure that we
can make limits be unlimited.
* init/event.c (event_copy): Function to copy an event structure.
* init/event.h: Add prototype.
* init/tests/test_event.c (test_copy): Make sure we copy the event
correctly, with or without arguments and/or environment.
* init/job.c (job_copy): Function to copy a job structure, leaving
the state as it is.
* init/job.h: Add prototype.
* init/tests/test_job.c (test_copy): Make sure that we copy the
job details whether they are NULL or non-NULL, but don't copy the
state.
* init/init.supp: Update supression.
* init/job.c (job_find_by_name): If we get a job that's an instance,
return what it's an instance of.
* init/tests/test_job.c (test_find_by_name): Restore accidentally
deleted test function; test that we get the real job, not an instance.
* init/job.c (job_new): instance_of is initialised to NULL.
* init/job.h: Add a new instance_of pointer, pointing to the parent
that we're an instance of.
* init/tests/test_job.c (test_new): Check that.
* init/tests/test_cfgfile.c (test_read_job): Make sure instance_of
pointers are updated.
* init/job.c (jobs): Store jobs in a hash table.
(job_new): Add to hash table, not to a list.
(job_handle_event, job_handle_event_finished, job_detect_stalled)
(job_free_deleted): Iterate across the hash table, rather than list.
(job_find_by_name): Use nih_hash_lookup, we keep this function because
we'll add "is instance or not" smarts soon!
(job_find_by_pid): Iterate across the entire hash table.
* init/tests/test_job.c (test_find_by_name): Drop test since this
function is now gone.
(test_free_deleted): Can't assume things are in a line now.
* init/control.c (control_job_list): Iterate the hash table.
* init/event.c: Don't hide the events list anymore
* init/event.h: Publish it and the init function.
* init/job.c: Don't hide the jobs list anymore.
(job_list): Since we don't hide it, we can drop this.
* init/job.h: Publish it and the init function.
* init/notify.c: Don't hide the subscriptions list anymore.
* init/notify.h: Publish it and the init function.
* init/control.c (control_job_list): Iterate the job list directly
* init/tests/test_control.c (test_event_emit): Use the events list
available to us.
* init/tests/test_event.c (test_poll): Call job_init directly and
just use the events list available to us.
* init/tests/test_job.c (test_new): Call job_init directly.
(test_change_state): Use the events list available to us.
* init/tests/test_notify.c (test_unsubscribe): Use the subscriptions
list available to us.
* doc/states.dot: Add updated state graph.
* doc/Makefile.am (EXTRA_DIST): Ship the states diagram.
(states.png): Include rules to build the png, we'll put it in bzr
anyway, but this is useful.
* init/cfgfile.c (cfg_delete_handler): Handle deleted jobs; mark
the job as deleted, and if it's dormant, invoke a state change.
* upstart/enum.h: Add a new JOB_DELETED state.
* upstart/enum.c (job_state_name, job_state_from_name): Add the new
state to the string functions.
* upstart/tests/test_enum.c (test_state_name)
(test_state_from_name): Check the enum works.
* init/job.c (job_change_goal): New decision; we can start a waiting
job if it's marked delete (it might be a new instance) -- we'll use
the new deleted state to decide that we shouldn't.
(job_change_state): Once we reach waiting, if the job is to be deleted,
move to the next state.
(job_next_state): The next state for a waiting job if the goal is stop
is deleted. We should never call job_next_state () for a deleted job.
(job_free_deleted): Very simple function, just detects
deleted jobs and frees them.
* init/job.h: Add prototype for new function.
* init/tests/test_job.c (test_change_goal): Update test to use new
deleted state; and don't even change the goal.
(test_change_state): Add a check to make sure we end up in deleted.
(test_next_state): Make sure waiting goes to deleted.
(test_free_deleted): Check the function.
* init/job.c (job_change_goal): Don't try and start a job if it's
marked to be deleted and is just waiting for cleanup.
* init/tests/test_job.c (test_change_state): Make sure that the cause
is released when we reach waiting.
* init/tests/test_cfgfile.c (test_read_job): Make sure that a deleted
job gets resurrected.
* init/cfgfile.c (cfg_visitor): Correct number of arguments and call
to cfg_job_name.
* TODO: Update.
* init/cfgfile.c (cfg_stanza_daemon): Don't allow arguments anymore.
* init/tests/test_cfgfile.c (test_stanza_daemon): Update tests.
* init/job.c (job_handle_event_finished): Function to unblock all
jobs blocked on a given event emission.
(job_new, job_emit_event): Rename blocker to blocked; it's useful for
testing for truth.
* init/job.h: Add prototype, rename member.
* init/tests/test_job.c (test_handle_event_finished): Test it.
(test_new, test_change_state): Update name here too.
* init/event.c (event_finished): Call job_handle_event_finished
function to unblock jobs.
* init/tests/test_event.c (test_poll): Make sure the job gets
unblocked; a few other tests have to change since running event_poll
always unblocks the job if nothing listens to it.
* init/job.c (job_child_reaper): Set failed back to FALSE if
we're respawning, since we don't want to be failing.
* init/tests/test_job.c (test_child_reaper): cause will be NULL.
also free and poll events when done.
(test_handle_event): pid can never be -1
(test_change_state): poll events when done
* init/tests/test_job.c (test_child_reaper): Process will always
be zero on return from reaper.
* init/tests/test_job.c (test_child_reaper): Killed doesn't go past
stopping; it goes to waiting, which will clear the cause.
* init/tests/test_job.c (test_child_reaper): Fill in values before
we test against them.
* init/tests/test_job.c (test_kill_process): Fix violated assertion
* init/tests/test_job.c (test_change_state): This should be failed
because nothing cleared it.
* init/tests/test_job.c (test_change_state): Fix a couple of array
index problems.
* init/tests/test_job.c (test_change_state): Why set that which
does not change?
* init/tests/test_job.c (test_change_state): Add newline to test.
* init/job.c (job_emit_event): Add the job name as an argument;
oops.
* init/tests/test_control.c (test_job_stop): Need to kill the process
ourselves, as we're blocked on an event.
(test_job_query): Fix wrong value in test.
(check_job_stopped, test_job_stop, test_unwatch_jobs): Change job
name to match the test.
* init/job.c (job_change_state): Must only not enter some states
with no process now; others like killed actually usually want one!
* init/tests/test_cfgfile.c (test_read_job): Fix test case.
* init/tests/test_job.c (test_handle_event): Clean up tests.
(test_detect_stalled): Clean up.
* init/job.c (job_child_reaper): Update the reaping of the child
processes; there's a much larger state range for the main process
now, so that needs to be taken into account.
* init/tests/test_job.c (test_child_reaper): New test cases.
* init/job.c (job_next_state): Encapsulate the slightly odd three
exit states of running in this function, otherwise we'll end up
special-casing it in places I'd rather not think about.
(job_change_goal): Only change the state of a running job if it
has a process.
* init/tests/test_job.c (test_next_state): Add a test case for the
dead running job
(test_change_goal): Add test case for the dead running job
* init/tests/test_job.c (test_change_state): Add test cases for
the forgotten stopping to killed transition.
* init/job.c (job_kill_process, job_kill_timer): Just check the pid
and state, and no longer any need to notify jobs since we're just
called from one state amongst many.
(job_change_state): Skip over the killed state if there's no process.
* init/tests/test_job.c (test_kill_process): Update test cases.
* init/job.c (job_run_process): Simplify a little bit, no need to
do the state assertions here, just make sure there's no already
a process running.
* init/tests/test_job.c (test_run_command, test_run_script): Run
tests in the spawned state, since that's where we run the primary
command or script. Drop check for process state since that's no
longer set.
* init/job.c (job_change_state, job_next_state): Ok, here's the big
one ... rewrite this to use the new state transitions. This has
suddenly got a lot simpler and easier to read, this was definitely a
good idea.
(job_emit_event): Function to make emission of events easier.
(job_failed_event): replaces this one which wasn't so easy.
* init/tests/test_job.c (test_change_state): I can't say how much I
wasn't looking forwards to rewriting these test cases; anyway, it's
done now and I hope they're all right;
(test_next_state): Make sure the state transitions are correct too.
* init/job.h: Rename is_instance to delete and spawns_instance to
just instance.
* init/job.c (job_new): Update.
* init/tests/test_job.c (test_new): Update.
* init/cfgfile.c (cfg_stanza_instance): Update.
* init/tests/test_cfgfile.c (test_stanza_instance): Update.
* init/event.h: Correct the event names.
* init/job.h: Add blocker event member.
* init/job.c (job_new): Initialise it to NULL.
* init/tests/test_job.c (test_new): Check it.
* init/job.c (job_change_goal): Have a stab at this function with the
new state machine; it gets somewhat simpler (until we introduce the
second scripts), now we just induce things by a state change.
* init/tests/test_job.c (test_change_goal): Made easier (for now)
because we don't need to deal with processes and can just wait to
be blocked on an event.
2007-02-08 Scott James Remnant <scott@netsplit.com>
* init/cfgfile.c (cfg_read_job): Drop check for useless respawn script
(cfg_stanza_respawn): Drop handling of "respawn script"
* init/tests/test_cfgfile.c (test_stanza_respawn): Drop the checks
for "respawn script"
* init/job.h: Move things about a bit more; remove respawn_script
since that state is going away.
* init/job.c (job_new): Drop initialisation of process_state.
* init/tests/test_job.c (test_new): Improve the tests.
* init/main.c (STATE_FD): Remove this define, not used anymore.
* init/tests/test_event.c (test_poll): Update the event checking
to match what's likely to happen.
* init/event.h: Remove commented out bit.
* init/tests/test_notify.c (check_job_status, test_job): Correct
state usage to match a possible state.
* init/control.c (control_job_start, control_job_stop)
(control_job_query, control_job_list): Drop process state and
description from the job status messages we send back.
* init/tests/test_control.c (test_error_handler)
(check_job_started, test_job_start, check_job_stopped)
(check_job_stopping, test_job_query, check_job_starting)
(test_job_list, test_watch_jobs, test_unwatch_jobs): Remove
process_state and description, and update usage of job states.
* init/notify.c (notify_job): Don't include process state or
description in the job status message anymore.
* init/tests/test_notify.c (check_job_status, test_job): Update tests
* init/cfgfile.c (cfg_read_job): Drop the copying of the process_state
member, since it doesn't exist anymore.
* init/tests/test_cfgfile.c (test_read_job): Drop the check too.
* init/job.h (Job): Drop the process_state member.
* util/jobs.c (handle_job_status): Drop the process_state and
description arguments; output a process id only if it's greater
than zero.
* util/tests/test_jobs.c (test_start_action, test_list_action)
(test_jobs_action): Update tests to use newer states and arguments.
* util/events.c (handle_event_job_status): Simplify in the same way
* upstart/message.h: Remove process_state and description from the
job status event (we already had the foresight to not put them in
the event job status event).
* upstart/message.c (upstart_message_new, upstart_message_handle):
Update handling of the messages to reduce the arguments.
* upstart/tests/test_message.c (test_new, my_handler)
(test_handle): Update the tests for the new job status message.
* upstart/enum.h (JobState): Change the job states to the new set
of states that we've planned.
(ProcessState): Drop process state entirely; this information is now
contained in the single JobState field.
* upstart/enum.c (job_state_name, job_state_from_name): Update
strings to match the new state names.
(process_state_name, process_state_from_name): Drop these functions.
* upstart/tests/test_enum.c (test_state_name)
(test_state_from_name): Update test cases to match new names.
(test_process_state_name, test_process_state_from_name): Drop.
* init/main.c (main): Remove the logd hack for now.
* init/job.c (job_new): Change the default console to none for now.
* init/tests/test_job.c (test_new): Update test.
* init/cfgfile.c (cfg_stanza_console): Can't guard against duplicates
for a while.
* init/tests/test_cfgfile.c (test_stanza_console): Comment out dup test
* init/cfgfile.c (cfg_read_job): Remove the restriction that there
must be either an 'exec' or 'script' for a job; jobs without either
define states others can use.
* init/tests/test_cfgfile.c (test_read_job): Convert the test to
a "must work".
* init/job.c (job_change_state): Remove restriction that we must
have either a script or a command; having neither should just wedge
the job at the running rest state. Note that there's no way to get
it out yet, because we don't force that particular state change.
* init/tests/test_job.c (test_change_state): Make sure that works.
* init/job.c (job_change_cause): Put the knowledge about how to
change the cause into a separate function, since it's slightly
tricky.
(job_change_goal, job_change_state): Set the cause using the above
function.
* init/job.h (Job): Rename goal_event to cause, also shuffle things
around so that the state is mostly together.
* init/job.c, init/process.c, init/notify.c, init/cfgfile.c: Update
references (and comments) to match the new name.
* init/tests/test_job.c, init/tests/test_event.c,
init/tests/test_process.c, init/tests/test_cfgfile.c,
init/tests/test_notify.c: Likewise.
* init/job.c (job_child_reaper): Don't change the goal event; the
state changes will handle this.
(job_change_goal): Only dereference/reference the goal event if we're
actually changing it.
* init/tests/test_job.c (test_change_state, test_child_reaper):
Update tests to not assume that the goal event gets changed.
(test_kill_process): Eliminate race condition.
* init/job.c (job_child_reaper): Correct some problems with job and
event failure; we now don't overwrite an existing failure record,
and don't record failure if the main process failed and the goal was
stop; since we likely caused it.
* init/tests/test_job.c (test_child_reaper): More test cases.
* logd/event.d/logd.in: Stop on the new runlevel events, not the
shutdown event.
* compat/sysv/shutdown.c (shutdown_now): Emit an ordinary runlevel
change event now; including the INIT_HALT environment variable
* compat/sysv/man/shutdown.8: Update the manual
* compat/sysv/telinit.c: Now just sends out a runlevel event with
an argument giving the new runlevel.
* compat/sysv/man/telinit.8: Update description of the command.
* upstart/message.h: Remove the UPSTART_SHUTDOWN message.
* upstart/message.c (upstart_message_new, upstart_message_handle):
Remove handling for the shutdown message.
* upstart/tests/test_message.c (test_new, test_handle): Remove
tests against the shutdown message.
* init/control.c (control_shutdown): Remove the shutdown command
from the server.
* init/tests/test_control.c (test_shutdown): Remove tests for it.
* init/event.h: Remove the shutdown event.
* util/initctl.c: Remove the shutdown command reference.
* util/events.c (shutdown_action): Remove the command.
* util/events.h: Update.
* util/tests/test_events.c (test_shutdown_action): Remove tests.
* init/job.c (job_detect_idle): Rename to job_detect_stalled
(job_detect_stalled): Remove the idle state detection
(job_set_idle_event): Idle event has been removed.
* init/job.h: Update.
* init/tests/test_job.c (test_detect_idle): Rename to
(test_detect_stalled): and remove idle detection tests.
* init/main.c (main): Replace job_detect_idle with job_detect_stalled
* init/control.c (control_shutdown): Don't set the idle event.
* init/tests/test_control.c (test_shutdown): Don't detect the idle
event (and thus the second event)
* init/cfgfile.c (cfg_stanza_service): Parser for service stanza.
* init/tests/test_cfgfile.c (test_stanza_service): Test the service
stanza.
(test_stanza_respawn): Check that respawn implies service.
* TODO: Update.
* init/job.h (Job): Add a new service member.
* init/job.c (job_new): Service starts off as false.
(job_change_state): Check service instead of respawn.
* init/tests/test_job.c (test_change_state): Check with service
instead of respawn, since that's what we really mean.
* init/cfgfile.c (cfg_read_job): Copy a whole bunch more state
into the newly parsed job.
* init/job.c (job_run_process): Only output the first error.
* init/tests/test_cfgfile.c (test_read_job): Make sure important
things are copied.
* TODO: Update.
* init/main.c: Restore a much simplified version of the term
handler that doesn't try and copy across any state.
* compat/sysv/telinit.c: Update call to event_emit; we'll revisit
this shortly when we get rid of the shutdown event.
* util/events.c (handle_event): Add new id field (but ignore it)
Functio
(handle_event_job_status): New function to handle the new event.
(handle_event_finished): Function to handle the end of the event.
(emit_action): Send the newer event, and loop over replies until
we get a finished one.
* util/tests/test_events.c (test_emit_action): Update tests cases.
* init/control.c (control_event_emit): New function to handle the
new-style emit message.
* init/tests/test_control.c (test_event_emit): Make sure the new
message function behaves.
* init/event.c, init/job.c, init/main.c, init/tests/test_event.c,
init/tests/test_job.c: Completely drop the serialisation code, it's
getting out of date and in the way.
* init/event.h: Remove compatibility macros.
(EventEmission): Drop the callback function; it was too error prone
to try and do it this way, and we only ever wanted to release a job
anyway as control requests are better handled through the notify
interface.
(EventEmissionCb): Drop unused typedef.
* init/event.c (event_emit): Drop callback argument.
(event_finished): Don't call the callback
* init/tests/test_event.c: Update to avoid callbacks.
* init/job.c (job_change_state): Convert to using event_emit and
EventEmission.
(job_detect_idle): Drop extra arguments to event_emit.
* init/main.c (main, cad_handler, kbd_handler): Drop extra arguments
to event_emit.
* init/control.c (control_shutdown): Use event_emit instead of
event_queue.
* init/tests/test_control.c (test_shutdown): Convert to using
EventEmission.
(test_watch_events, test_unwatch_events): Drop extra arguments to
event_emit.
* init/tests/test_notify.c (test_subscribe_event, test_job)
(test_event, test_event_finished): Drop extra arguments to event_emit
* init/tests/test_job.c (test_change_goal, test_change_state)
(test_run_script, test_child_reaper, test_detect_idle): Drop
extra arguments to event_emit.
* init/tests/test_process.c (test_spawn): Drop extra arguments to
event_emit.
* TODO: Update.
Rewrite the notification subsystem quite significantly; now we
have individual functions to subscribe to different types of
notification, and can even subscribe to individual jobs or events.
* init/notify.c (notify_subscribe_job, notify_subscribe_event)
(notify_unsubscribe): New subscription and unsubscription functions
that assume one record per subscription, not process.
(notify_subscription_find): Function to find a subscription.
(notify_job): Send a message to anything subscribed to the goal event
as well.
(notify_event): Use EventEmission and include the id in the event.
(notify_event_finished): New function, sends a finished message and
includes both the id and whether the event failed.
* init/notify.h (NotifySubscribe): New notify structure that is
once per subscription, rather than per-process; and allows
subscription to individual jobs or events.
* init/tests/test_notify.c (test_subscribe_job)
(test_subscribe_event, test_unsubscribe): Test the new subscription
functions, replacing the old
(test_subscribe): tests.
(test_subscription_find): Check finding works
(check_event, test_event): Update to use emissions, and check that the
id is correct.
(test_event_finished): Check this one works too
(check_event_job_status, test_job): Make sure processes subscribed
via the goal event are notified too.
* init/event.c (event_pending): Pass the emission directly.
(event_finished): Notify subscribers that the event has finished.
* init/control.c (control_error_handler): Call notify_unsubscribe
(control_watch_jobs, control_unwatch_jobs, control_watch_events)
(control_unwatch_events): Update to the new subscription API.
* init/tests/test_control.c (test_error_handler): Use new API
(test_watch_jobs, test_unwatch_jobs, test_watch_events)
(test_unwatch_events): Also update these to the new API; use a
destructor to make sure the subscription is freed.
* init/tests/test_process.c: Don't use printf, use TEST_FUNCTION
2007-02-07 Scott James Remnant <scott@netsplit.com>
* upstart/message.h: Allocate new grouped event messages.
* upstart/message.c (upstart_message_new, upstart_message_handle):
Add support for the new grouped event messages.
* upstart/tests/test_message.c (test_new, test_handle)
(my_handler): Make sure the new messages are passed correctly.
* init/job.c (job_change_state): Clear the goal event whenever we
reach the final rest state of a job (waiting for all jobs, running
for services).
* init/tests/test_job.c (test_change_state): Check that the goal
event goes away at the right times.
* TODO: Update.
* init/tests/test_job.c (test_child_reaper): Make sure that the
event is marked failed properly
* init/job.c (job_start_event, job_stop_event): There's no reason
for these to exist as seperate functions anymore, especially since
we want to eventually have some kind of match table.
(job_handle_event): Perform the iterations and match calls here
instead, since we just call job_change_goal now.
* init/job.h: Remove prototypes.
* init/tests/test_job.c (test_start_event, test_stop_event): Fold into
(test_handle_event): which now handles all the cases.
* init/job.c (job_detect_idle): Call event_emit
* init/main.c (main, cad_handler, kbd_handler): Call event_emit
instead of event_queue.
* init/tests/test_event.c (test_new): Call event_poll
* init/tests/test_job.c (test_change_state, test_child_reaper)
(test_detect_idle, test_change_state): Update to use newer event API.
* TODO: Update.
* init/job.c (job_start, job_stop): Drop these functions; call
job_change_goal instead (which is now public).
(job_change_state, job_child_reaper): Call job_change_goal instead.
* init/job.h: Update.
* init/tests/test_job.c (test_start, test_stop): Merge into new
(test_change_goal): function.
* init/main.c (main): Call job_change_goal instead of job_start.
* init/control.c (control_job_start, control_job_stop): Call
job_change_goal instead.
* init/tests/test_job.c (test_new, test_change_state)
(test_run_script, test_start, test_stop, test_start_event):
* init/job.h (Job): goal_event is now an EventEmission, and is
a direct pointer to the one in the events queue, rather than a copy.
* init/process.c (process_setup_environment): Reference the event
name and environment through the goal event, not directly.
* init/job.c (job_run_script): Reference the event name and
environment through the goal event, not directly.
(job_change_state, job_child_reaper): Replace direct setting of the
job goal with a call to job_stop; the process state is always
PROCESS_NONE in all three cases, so this is completely safe.
(_job_start, _job_stop): Merge these two functions together into
(job_change_goal): which behaves a lot more like job_change_state,
except that it doesn't loop. This handles the changing of the
emission.
(job_start, job_start_event, job_stop, job_stop_event): Simplify
these functions, now they just call job_change_goal passing in
the emission pointer (or NULL).
* init/main.c, init/job.c, init/job.h, init/event.c, init/event.h,
init/tests/test_job.c, init/tests/test_event.c: Remove state
serialisation code for the time being; maintaining it is getting
increasingly harder, and it introduces some major bugs. It will
get rewritten shortly.
* init/event.c (event_pending): Pass the emission directly to
job_handle_event now.
* init/job.c (job_handle_event, job_start_event, job_stop_event):
Deal with event emissions rather than just plain events, the change
so far doesn't do anything else other than take the structure change.
* init/job.h: Change prototypes.
* init/tests/test_job.c (test_start_event, test_stop_event)
(test_handle_event): Update tests to use emissions.
* init/tests/test_event.c (test_read_state, test_write_state): Check
the passing of the progress information.
* init/event.c (event_read_state, event_write_state): Add progress
field to the serialisation (oops).
* init/event.h: Add missing attribute for event_read_state.
* init/cfgfile.h: Add missing attributes.
* init/main.c (read_state): Don't discard return value.
* TODO: Update.
* init/main.c (read_state): Handle the Emission keyword; also handle
Event really being an EventEmission.
* init/event.c (event_emit): Make the next emission id a static global
(event_read_state, event_write_state): Serialise event emission
structures, not plain events; also send over the last id we used so
it appears seamless. This doesn't yet handle the callback/data bit
of the serialisation, which turns out to be a little tricky ... oops
* init/event.h: Update.
* init/tests/test_event.c (test_read_state, test_write_state): Check
that serialisation is done with EventEmissions instead, and all the
fields are passed (except callback and data which are ... tricky).
* init/main.c (main): Call event_poll instead of event_queue_run.
* init/event.c (event_poll): Add the new function that replaces
event_queue_run(); handles the new-style event emission structures
in the list and only returns when there are no non-handling events.
(event_pending, event_finished): Handling of particular event states
during poll; split out for readability.
(event_queue, event_queue_run): Drop these obsolete functions.
(event_read_state): Force type from event_queue.
* init/event.h: Add event_poll prototype; remove prototypes of old
functions, replacing with #defines for now so things still compile.
* init/tests/test_event.c (test_queue): Drop tests.
(test_read_state, test_write_state): Force type from event_queue
Change type we check size of.
(test_poll): Pretty thoroughly test the new poll function.
* init/job.c (job_change_state): Force type from event_queue
* init/control.c (control_event_queue): Force type from event queue
* init/tests/test_job.c (test_detect_idle): Force type from event_queue
* init/tests/test_control.c (test_event_queue, test_shutdown):
Force type from event_queue
* init/event.c: Revert to a single list of events with an enum
(event_emit): Set the progress to pending initially.
(event_emit_find_by_id): Simplify now it just checks one list
(event_emit_finished): Function for jobs to call once they've done
with an event; just sets the progress to finished for the event
queue to pick up.
* init/tests/test_event.c (test_emit_finished): Check it.
* init/event.h: Add prototype.
(EventProgress): Add new enum
(EventEmission): And add progress member to this structure
* init/tests/test_event.c (test_emit): Make sure the event is pending
* init/event.c (event_emit_find_by_id): Locate an event emission
by its id in either the pending or handling queue.
* init/event.h: Add prototype
* init/tests/test_event.c (test_emit): Make sure that the emission
id is unique each time.
(test_emit_find_by_id): Test the function.
* init/event.c (event_emit): New function to replace event_queue();
returns an EventEmission structure with the details filled in as
given.
* init/event.h: Add prototype.
* init/event.c (event_init): Rename the single events queue to
pending and add a new handling list.
* init/event.h (EventEmission, EventEmissionCb): Add a new emission
structure that wraps an event, for use in the queue.
* util/tests/test_events.c (test_events_action): Update test now
that nih_message is more sensible.
* util/tests/test_jobs.c (test_start_action, test_list_action)
(test_jobs_action): Update test
* util/events.c (emit_action): Actually pass the emit_env array
* util/tests/test_events.c (test_emit_action): Make sure it does.
* util/initctl.c (main): Catch nih_command_parser() returning a
negative value to indicate an internal error, and always exit 1.
* util/events.c (handle_event): Build up multiple lines to describe
the event, including its arguments and environment.
* util/tests/test_events.c (test_events_action): Check the new output
format is right.
* init/main.c (main): Take out inadvertantly leaked debugging code;
sorry about that.
* init/job.c (job_child_reaper): Rewrite this to make the logic a
little easier to follow, and support signals in normalexit. This
also now applies to deciding whether the job failed, if it did, we
store that information in the job so the stop and stopped events
can get it.
* init/tests/test_job.c (test_child_reaper): Add new test cases for
the setting of the failed flags.
* init/cfgfile.c (cfg_stanza_normalexit): Allow signal names in the
arguments, which are added to the normalexit array or'd with 0x80
* init/tests/test_cfgfile.c (test_stanza_normalexit): Check that we
can now parse signal names correctly.
* init/job.c (job_failed_event): Change add to addp to fix leak.
* init/job.c (job_failed_event): Function to turn an event into one
that includes all the necessary arguments and environment.
(job_change_state): Call job_failed_event for the stop and stopped
events (bit hacky at the moment, will improve later).
* init/tests/test_job.c (test_change_state): Check that the failed
events are generated properly.
2007-02-06 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_change_state): Reset the failed member when
we enter the starting state.
* init/tests/test_job.c (test_change_state): Make sure that the
failed member is reset when we enter the starting state.
* init/job.h (Job): Add failed, failed_state and exit_status members.
* init/job.c (job_new): Initialise new members.
* init/job.c (job_child_reaper): Convert signals to names when
outputting status messages.
* init/tests/test_job.c (test_child_reaper): Check that the signal
name gets converted over.
* init/event.h (CTRLALTDEL_EVENT): Now we've broken the shared
namespace of events and jobs, rename the control-alt-delete event
back to control-alt-delete.
* init/job.c (job_change_state): Replace the events generated as
part of the job state, named for the job and state, with new state
events that have the job name as an argument.
* init/event.h: Define new job event names.
* init/tests/test_job.c (test_change_state): Make sure the new
events are correct, with the job name as an argument.
* init/job.c (job_change_state): Remove the job event; this has
been repeatedly proved to be confusing.
* init/tests/test_job.c (test_change_state): Remove checks for the
job event.
* util/events.c (emit_action): Pass in extra arguments.
(env_option): Function to parse an option given an environment
variable.
* util/events.h: Add prototype.
* util/tests/test_events.c (test_emit_action): Make sure that the
emit action works with no arguments and with arguments.
(test_events_action): Send back events with the right number of args.
(test_env_option): Check the env option parser works.
* util/initctl.c: Give shutdown its own command and options, give
emit a new -e option.
* util/events.c (shutdown_action): Split out from emit, seeing as
these are going to be different from now on.
* util/events.h: Add prototype.
* util/tests/test_events.c (test_shutdown_action): Copy test cases.
* init/control.c (control_event_queue): Take the arguments and
environment from the event queue request; and reparent into the
event.
* init/tests/test_control.c (test_event_queue): Check that arguments
and environment are copied across properly.
* init/notify.c (notify_event): Pass in the arguments and environment
for the event.
* init/tests/test_notify.c (check_event): Check for event arguments
and environment from the notify process.
(test_event): Add arguments and environment to the event we test with
* upstart/tests/test_message.c (test_new, test_handle): Send
arguments and environment with the UPSTART_EVENT_QUEUE and
UPSTART_EVENT messages.
* upstart/wire.c (upstart_pop_int, upstart_pop_unsigned): Shrink
only once.
(upstart_pop_string): Check the length is at least one first, as
we may just have an 'S'.
* upstart/message.c (upstart_message_new, upstart_message_handle):
The UPSTART_EVENT and UPSTART_EVENT_QUEUE messages gain new array
arguments containing the arguments and environment for the event.
* upstart/message.h: Document the new arguments.
* util/tests/test_events.c, util/tests/test_jobs.c: Update the
message format checks here too.
* upstart/tests/test_wire.c (test_pop_pack): Free the array.
* upstart/tests/test_message.c (test_new, test_handle)
(test_handle_using, test_reader): Update tests to include and
expect new type markers between each field.
* upstart/wire.c (upstart_push_int, upstart_push_unsigned):
Take out silly asserts; it must have room!
* upstart/wire.c (upstart_push_string, upstart_pop_string): Rewrite
to use a type like the rest of the functions; this removes the strange
length restriction and allows us to make the pop function
non-destructive.
* upstart/tests/test_wire.c (test_push_string): Update.
(test_pop_string): Update, adding in non-destructive, wrong type
and insufficient space for type test cases.
(test_push_array, test_pop_array): These needed updated too,
changing the string format changed the array format.
(test_push_pack, test_pop_pack): And obviously the pack format changed.
* upstart/wire.c (upstart_pop_header): Make the function
non-destructive in the face of errors.
* upstart/tests/test_wire.c (test_pop_header): Make sure that
invalid headers are non-destructive on error.
* upstart/tests/test_wire.c (test_pop_int, test_pop_unsigned):
Make sure that insufficient space is non-destructive.
* upstart/wire.c (upstart_push_int, upstart_pop_int)
(upstart_push_unsigned, upstart_pop_unsigned): Convert to array-style
type first format.
(upstart_push_string, upstart_push_header): Write the length and
type fields out by hand so they don't get an 'i' prefix.
(upstart_pop_string, upstart_pop_header): Read the length and type
fields by hand so they don't get an 'i' prefix.
* upstart/tests/test_wire.c (test_push_int, test_pop_int)
(test_push_unsigned, test_pop_unsigned): Update test cases to match.
(test_push_pack, test_pop_pack): Pack format was changed too.
* upstart/wire.c (upstart_push_packv, upstart_pop_packv): Add calls
to push and pop array.
* upstart/tests/test_wire.c (test_push_pack, test_pop_pack): Test
support for arrays.
* upstart/wire.c (upstart_push_array, upstart_pop_array): Implement
new array functions; note that these use a newer format that allows
us to transmit NULL without needing to limit the size of the array.
* upstart/wire.h: Add prototypes.
* upstart/tests/test_wire.c (test_push_array, test_pop_array):
Test the new array functions.
* init/job.c (job_run_script): Build up the argument list, appending
those from the goal event if one is set.
(job_run_command): Use nih_str_array_add to build up the arguments,
but don't append those from the goal event (use script).
* init/tests/test_job.c (test_run_script): Make sure the arguments get
passed to the running shell scripts.
* init/job.c (job_run_script): Only use the /dev/fd trick if we can
actually stat /dev/fd; also don't hardcode that path ...
* init/paths.h (DEV_FD): Add here.
* init/process.c (process_setup_environment): Copy environment
variables from the goal event into the job's process.
* init/tests/test_process.c (test_spawn): Make sure the environment
reaches the job, but doesn't override that in the job already.
* init/tests/test_job.c (test_start_event):
* init/job.c (job_start_event, job_stop_event): Copy the arguments
and environment from the event into the goal event.
* init/job.c (job_read_state, job_write_state): Read and write
arguments and environment for goal event.
* init/tests/test_job.c (test_read_state, test_write_state): Test
with arguments and environment to the goal event.
* init/event.c (event_read_state, event_write_state): Read and write
the arguments and environment of the event.
* init/tests/test_event.c (test_read_state, test_write_state): Make
sure arguments and environment are correctly serialised.
* init/cfgfile.c (cfg_stanza_console): Fix a leak of the console
argument in the case of duplicated options.
(cfg_stanza_env): Drop the counting now nih_str_array_addp does it;
and be sure to use that function.
(cfg_stanza_umask): Fix leak of umask argument
(cfg_stanza_nice): Fix leak of nice argument
* init/tests/test_event.c (test_new): Call event_queue_run so init
is called outside of a TEST_ALLOC_FAIL block.
* init/event.c (event_new): Start off with NULL args and env, to
match job (saves a few bytes).
(event_match): Watch for NULL arguments!
* init/tests/test_event.c (test_new): Check for NULL not alloc'd
* init/cfgfile.c (cfg_stanza_on, cfg_stanza_start)
(cfg_stanza_stop): Parse arguments to the on stanza and store them
directly in the event.
* init/tests/test_cfgfile.c (test_stanza_on, test_stanza_start)
(test_stanza_stop): Make sure arguments are parsed into the event.
* init/event.c (event_new): Use nih_str_array_new.
* init/cfgfile.c (cfg_stanza_env): Rewrite to use nih_str_array.
* init/job.c (job_run_script): Check the error returned from
nih_io_reopen; don't just loop. We only ever expect ENOMEM (the
other error, EBADF, is impossible).
* init/job.c (job_change_state): Reset the goal_event to NULL when
we catch a run-away job (as it's not stopping for the same event
it started with).
(job_child_reaper): Reset the goal_event to NULL after setting the
goal to STOP.
* init/tests/test_job.c (test_change_state, test_child_reaper):
Check that the goal event gets reset whenever the goal gets changed.
* init/tests/test_event.c: Use TEST_ALLOC_FAIL
* init/event.c (event_match): Match arguments using fnmatch() and
allow more arguments in event1 than event2 (but not the other way
around).
* init/tests/test_event.c (test_match): Check the new permitted
combinations.
* init/event.h (Event): Add args and env members to Event.
* init/event.c (event_new): Initialise args and env members to
zero-length arrays.
* init/tests/test_event.c (test_new): Use TEST_ALLOC_FAIL and
make sure args and env are both initialised to a list containing
just NULL.
* util/jobs.c (start_action): Get the UPSTART_JOB environment variable
and use that if we don't have any arguments passed to us.
(do_job): Code split from the above function that handles a named job
* util/tests/test_jobs.c (test_start_action): Make sure UPSTART_JOB
is picked up.
* init/process.h: Add necessary attributes.
* init/process.c (process_setup_environment): Set the UPSTART_JOB
environment variable from the job, and the UPSTART_EVENT environment
variable from the job's goal_event member (if set).
* init/tests/test_process.c (test_spawn): Make sure we get the
environment in the job.
* init/job.h: Add attributes to job_new and job_read_state.
* init/tests/test_job.c: Use CHECK_ALLOC_FAIL on the functions we
didn't get around to touching while we were in here.
* init/job.c (job_start_event, job_stop_event): Set the goal_event
member to a copy of the event we found.
(job_read_state): Use event_new instead of trying to do it by hand.
* init/tests/test_job.c (test_start_event, test_stop_event): Use
CHECK_ALLOC_FAIL; and make sure the goal_event is set properly.
(test_start, test_stop, test_write_new): Use event_new here too
* init/job.c (job_write_state): Output a goal_event field containing
the event name or nothing for NULL.
(job_read_state): Parse the goal_event field
* init/tests/test_job.c (test_write_state): Make sure the state is
written out properly.
(test_read_state): Make sure that the state is parsed correctly too.
* init/job.c (job_start, job_stop): Split all of the code except
the goal_event setting into two new static functions that this calls
(_job_start, _job_stop): New static functions
(job_start_event, job_stop_event): Call _job_start and _job_stop
instead of job_start and job_stop
* init/job.c (job_catch_runaway): Move this function up a bit.
* init/job.c (job_start, job_stop): Clear the goal_event member,
these functions are called for a manual start.
* init/tests/test_job.c (test_start, test_stop): Make sure the
goal_event member is freed and set to NULL.
* init/job.h (Job): Add a new goal_event member
* init/job.c (job_new): Initialise the goal_event member to NULL.
* init/tests/test_job.c (test_new): Check with TEST_ALLOC_FAIL;
also make sure goal_event is initialised to NULL.
2007-02-05 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.3.3
* NEWS: Update.
* init/process.c (process_spawn): Exit with 255 so we don't clash
with anything that uses 1 as a normal exit code. Note why we only
close 0..2 (everything else is FD_CLOEXEC).
* init/cfgfile.c (cfg_watch_dir): Mark the inotify watch descriptor
as FD_CLOEXEC.
* init/control.c (control_open): nih_io_set_cloexec can only ever
return EINVAL, so no point checking it.
2007-02-04 Scott James Remnant <scott@netsplit.com>
* init/tests/test_control.c: Remove strange old code.
2007-02-03 Scott James Remnant <scott@netsplit.com>
* init/control.c (control_open_sock, control_reopen)
(control_close_handler): Drop these functions; unconnected datagram
sockets don't close -- so why try dealing with it?
(control_error_handler): Don't reopen the socket on error, just log
it -- the socket should be fine, there's no remote end to be lost,
after all.
* init/tests/test_control.c (test_close_handler): Drop.
(test_error_handler): Drop the reopen tests.
* init/tests/test_job.c (test_run_script): Control socket doesn't
get unexpectedly opened anymore; so no need to close it.
* init/control.c (control_open): Remove the strange behaviour that
this can be called to get the socket. Instead make control_io
global; we're all adults after all.
* init/tests/test_control.c (test_open): Remove the test for the
silly behaviour.
* init/notify.c (notify_job, notify_event): Use the control_io
pointer directly, and just do nothing if we lost it somehow.
* init/main.c (main): Being unable tp open the control socket, or
parse the configuration, should be a fatal error; stop being so
damned liberal! <g> Don't reset the signal state if we're
being restarted, as this loses any pending signals -- be happy
that our parent left them in a good state. Set SIGCHLD to the
standard handler, otherwise we might lose this before we start
the main loop (which does the same anyway).
(term_handler): Rework so we don't need to close and open the
control socket; instead we just close it in the child that's
going to send the state, and notify the parent that it's safe to
exec (which will cause it to be closed so the new init can open it).
* init/tests/test_control.c (test_open): Fix valgrind error
* init/tests/test_notify.c (test_subscribe): Fix valgrind error
* init/notify.c (notify_subscribe): Make safe against ENOMEM.
* init/tests/test_notify.c (test_subscribe): Use TEST_ALLOC_FAIL
* init/control.c: Add needed attributes; tidy up formatting.
(control_open): Don't let ENOMEM fail opening the control socket.
* init/control.h: Add needed attributes.
* init/tests/test_control.c (test_open): Test for failed allocation.
* init/main.c (term_handler): Make sure we catch failure to open
the control socket again.
* TODO: Update
* init/cfgfile.c (cfg_watch_dir): Clean this up a bit; now we only
output a warning if inotify failed for any reason other than not
being supported AND walking worked.
* init/cfgfile.c (cfg_watch_dir): Update to even newer watch API;
our create_handler is now always called if inotify is successful,
so we just need to fall back to walking the directory when it
isn't -- if inotify isn't supported, don't even bother complaining.
(cfg_create_modify_handler): Check the stat of the file visited to
make sure it's a regular file.
(cfg_visitor): Check the stat of the file visited to make sure it's
a regular file.
* init/cfgfile.c: Update include to upstart/enum.h
* init/job.c: Update include to upstart/enum.h
* init/job.h: Update include to upstart/enum.h
* logd/main.c: Add attribute to open_logging
* util/initctl.c: Split out the command functions into new files;
* util/jobs.c: This gets the job-related commands
* util/events.h: This gets the event-related commands
* util/initctl.h, util/jobs.h, util/events.h: Headers
* util/tests/test_jobs.c: Test suite for job-related commands.
* util/tests/test_events.c: Test suite for event-related commands.
* util/Makefile.am (initctl_SOURCES): Add new files.
(TESTS): Build new test suites.
(test_jobs_SOURCES, test_jobs_LDFLAGS, test_jobs_LDADD):
Details for job-related commands test suite binary.
(test_events_SOURCES, test_events_LDFLAGS, test_events_LDADD):
Details for event-related commands test suite binary.
* TODO: Remove item about splitting initctl now we've done it.
* TODO: Big update; strip anything we have a spec for.
* upstart/message.c (upstart_message_handle): Make sure that if we
fail to parse a message, we don't leave strings around in memory.
* upstart/tests/test_message.c (test_open): Check that we get a
raised EADDRINUSE if we try an open a socket twice.
(test_handle): Add lots of checks for things like NULL names and
incomplete messages; as well as the obvious unknown message.
(test_reader): Make sure that errors while handling messages are
dealt with by logging it.
* upstart/job.c, upstart/job.h, upstart/tests/test_job.c: Rename to
enum.c, enum.h and tests/test_enum.c; since this just includes enums
and convert functions really.
* upstart/Makefile.am: Update.
* upstart/libupstart.h: Update include.
* upstart/tests/test_message.c: Update include.
2007-02-01 Scott James Remnant <scott@netsplit.com>
* logd/main.c (main): Ensure we error if daemonise fails.
* compat/sysv/shutdown.c (main): Ensure that signals and timers
are added, even if we run out of memory.
* upstart/tests/test_message.c: Change from assert to assert0
* upstart/tests/test_wire.c: Change from assert to assert0
* init/tests/test_notify.c: Change from assert to assert0
* init/tests/test_control.c: nih_io_message_send should always return
a value greater than zero.
* upstart/tests/test_wire.c: Change to use assert instead of NIH_ZERO;
the rationale here is that in test cases we just want to fail, not
try again repeatedly.
* upstart/tests/test_message.c: Likewise.
* init/tests/test_control.c: Use assert to ensure we get the expected
return values of functions that raise errors.
* init/tests/test_notify.c: Use assert to ensure we get the expected
return values of functions that raise errors.
* init/cfgfile.c (cfg_watch_dir): Port to the new NihWatch API and
use nih_dir_walk(). This also fixes the long-standing bug where we
wouldn't watch the configuration directory if inotify was disabled.
Drop both the parent and prefix members for now, until we clean this
up later.
(cfg_create_modify_handler): Wrap cfg_read_job after figuring out
the job name.
(cfg_job_name): Function to figure out the job name from a path.
(cfg_visitor): Visitor function to handle initial parsing, figuring
out the job name; otherwise identical to the standard handler.
* init/cfgfile.h: Update prototype for cfg_watch_dir.
* init/main.c (main): Update call to cfg_watch_dir.
2007-01-31 Scott James Remnant <scott@netsplit.com>
* upstart/tests/test_message.c: Use TEST_ALLOC_FAIL to make sure
allocations are handled properly.
2007-01-30 Scott James Remnant <scott@netsplit.com>
* upstart/wire.c: Note that if any of the push functions fail, the
entire buffer should be discarded.
* upstart/tests/test_wire.c (test_push_int, test_push_unsigned)
(test_push_string, test_push_header, test_push_pack): Us
TEST_ALLOC_FAIL to ensure that failing to allocate memory is caught.
* upstart/tests/test_message.c (my_handler): Free the name and
description after checking; they aren't otherwise.
* upstart/wire.c (upstart_push_packv, upstart_pop_packv): Consume
a copy of the va_list, so these can be called multiple times on the
same list without ill effect.
* upstart/message.h: Add warn_unused_result attributes to
upstart_message_handle and upstart_message_handle_using as they raise
errors.
* upstart/wire.c: push functions return negative values to indicate
insufficient memory.
* upstart/wire.h: Add warn_unused_result attributes to push functions
* upstart/tests/test_message.c: Guard calls to nih_io_buffer_push and
nih_io_message_add_control with NIH_ZERO to ensure they succeed.
* upstart/tests/test_wire.c: Guard calls to nih_io_buffer_push
* HACKING: Update from libnih with new Documentation,
Function Attributes and Test Cases sections.
2007-01-10 Scott James Remnant <scott@netsplit.com>
* init/main.c (crash_handler): s/SEGV/SIGSEGV/
* init/main.c (main): Rename variable
* TODO: Update.
* init/main.c (main): Change the way we clear the arguments; by
deleting just the final NULL terminator, we fool the kernel into
only returning one argument in cmdline.
* init/main.c (segv_handler): Rename to crash_handler and handle
SIGABRT as well, so we can catch assertion errors. Of course, in
theory, with our high test converage this should never happen in
practice <chortle>
2007-01-09 Scott James Remnant <scott@netsplit.com>
* init/main.c (main): Clear arguments so that upstart only ever
appears as /sbin/init in ps, top, etc.
* TODO: Update.
* util/initctl.c: Add data pointer to functions and handle calls.
* init/control.c: Add data pointer to all functions.
* init/tests/test_control.c: Pass data pointer to
upstart_message_handle_using()
* init/tests/test_notify.c: Pass data pointer to
upstart_message_handle_using()
* upstart/message.c (upstart_message_handle)
(upstart_message_handle_using): Add a data pointer argument to these
functions and pass it to the handler.
(upstart_message_reader): Pass the io structure's data pointer.
* upstart/message.h (UpstartMessageHandler): Add a data pointer to
the message handler.
* upstart/tests/test_message.c (test_handle, test_handle_using):
Pass a data pointer to the function call and check it's passed
to the handler correctly.
(test_reader): Check that the io data pointer gets passed.
* init/tests/test_cfgfile.c (test_stanza_console, test_stanza_env)
(test_stanza_umask, test_stanza_nice, test_stanza_limit): Finish off
the newer style test cases.
* init/cfgfile.c (cfg_stanza_console, cfg_stanza_umask)
(cfg_stanza_nice, cfg_stanza_limit, cfg_stanza_chroot)
(cfg_stanza_chdir): Guard against duplicate uses of the stanzas.
* init/tests/test_cfgfile.c (test_stanza_daemon)
(test_stanza_respawn): Check that neither daemon or respawn override
exec if they have no arguments.
(test_stanza_script): Add missing function
(test_stanza_chroot, test_stanza_chdir): Add tests for these simple
stanzas.
* init/cfgfile.c: Change remaining uses of nih_error_raise and
return to just nih_return_error.
* init/cfgfile.c (cfg_stanza_exec, cfg_stanza_daemon)
(cfg_stanza_respawn, cfg_stanza_script): Disallow duplicates,
both of command strings, scripts, limits and of just the flags.
* init/tests/test_cfgfile.c (test_stanza_exec)
(test_stanza_daemon, test_stanza_respawn, test_stanza_instance):
Check the behaviour of these stanzas.
* init/cfgfile.c (cfg_stanza_start, cfg_stanza_stop): Disallow
duplicate values for the script.
* init/tests/test_cfgfile.c (test_stanza_start, test_stanza_stop):
Test cases for those two functions.
* init/cfgfile.c (cfg_stanza_description, cfg_stanza_author)
(cfg_stanza_version): Don't allow stanza to be duplicated anymore.
* init/tests/test_cfgfile.c (test_stanza_description)
(test_stanza_author, test_stanza_version): Test cases for these
simple stanza; making sure duplication is not permitted.
(test_stanza_on): Add a test case for this stanza too.
* init/cfgfile.c (cfg_stanza_kill): Guard against duplicate uses
of the kill timeout stanza.
* init/tests/test_cfgfile.c (test_stanza_kill): Test the complex
kill stanza.
(test_stanza_pid): Check duplicate usage results in an error.
* init/job.h (Job): Rename pidfile to pid_file and binary to pid_binary
* init/job.c (job_new): Update names here too.
* init/errors.h: Add a new "duplicate value" error.
* init/cfgfile.c (cfg_read_job): Change name of variables, and catch
the duplicate value error to add the line number.
(cfg_stanza_pid): Change variable names, and clean this function up
a little. Make it an error to use a stanza more than once.
* init/tests/test_cfgfile.c (test_stanza_pid): Write a newer test
case function for the pid stanza.
* init/cfgfile.c (cfg_stanza_normalexit): Use do/while instead of
while, that we don't have to test has_token first as next_arg does
that for us.
* init/cfgfile.c (cfg_stanza_normalexit): Change to peek at the next
token to see whether it's missing or not, and then just fetch each
next argument at a time. This is more efficient than parsing them
all in one go, and also means we can report the error in the right
place!
* init/tests/test_cfgfile.c (test_stanza_normalexit): Since we've
changed the function that parses the stanza, add a proper test case
function for it, covering all the behaviours.
* init/job.c (job_new): Initialise the emits member to an empty list.
* init/job.h (Job): Add the emits member as a list.
* init/tests/test_job.c (test_new): Check the emits list starts off
empty.
* init/tests/test_cfgfile.c (test_stanza_emits): Test the new emits
stanza; this function will also serve as a prototype for cleaning up
the config tests.
* init/cfgfile.c (cfg_stanza_emits): Add function to parse the new
emits stanza.
* init/cfgfile.c (cfg_stanza_depends): Remove the depends stanza
from the configuration file. Dependency support has never been used,
and is to be replaced by a more flexible event/state configuration
and blocking on the starting/stopping events.
* init/tests/test_cfgfile.c: Remove references and tests for the
depends stanza.
* init/job.h: Remove the depends list from the job structure.
* init/job.c (job_new): No depends list to initialise.
(job_change_state): No dependencies to release
(job_start): No dependencies to iterate; this removes a particularly
hairy and complex interaction between state changes. Remove the
dependency event.
(job_release_depends): Drop this function.
* init/tests/test_job.c (test_start, test_stop): Massively simplify
these tests cases now we don't have dependencies to worry about.
(test_release_depends): Drop tests
2007-01-08 Scott James Remnant <scott@netsplit.com>
* init/cfgfile.c: Rewrite using the nih_config API, rather than one
huge function we now just have seperate handler functions for each
stanza. We can also use more fine-grained parsing than slurping
all args in and counting them.
(cfg_read_job): Catch exceptions from the configuration parser and
add the line number where the problem occurred to an output message.
Parser errors are now fatal, and not ignored.
* init/errors.h: Add a file containing errors raised within the init
daemon codebase.
* init/Makefile.am (init_SOURCES): Build with errors.h
* init/tests/test_cfgfile.c: Update test cases now we don't expect
a job to be returned if there's a parser error.
* TODO: Update
2007-01-06 Scott James Remnant <scott@netsplit.com>
* logd/main.c (logging_reader): Fix inadvertent shadowing of the
len parameter.
* compat/sysv/telinit.c: Oops, nearly forgot to port this to send
the messages in the new way.
* compat/sysv/shutdown.c (shutdown_now): Likewise, port this too.
* TODO: Update.
* util/initctl.c (handle_job_status): Output the process argument,
not the pid argument which contains the origin of the message.
* upstart/message.c (upstart_message_handle): Raise a new unknown
message error if we don't have a handler and a new illegal message
error if the source is illegal.
* upstart/tests/test_message.c (test_handle): Adjust tests to check
for the new errors that we raise.
* upstart/errors.h: Define strings for new errors.
* util/initctl.c: Yet another makeover for this little program,
port it to the new message/control framework using handler functions
and NihIoMessage. This starts to make each action function look
very similar, so there's method to this madness.
2007-01-05 Scott James Remnant <scott@netsplit.com>
* logd/main.c (main): Make sure that we add the SIGTERM handler.
* init/tests/test_job.c (test_run_script): This test case relies
on there only being one file descriptor watch, which won't be true
if the control socket has been opened because there's a message to
go out. Make sure it's closed first.
* init/init.supp: Update supressions file now that control_init
has been renamed to notify_init
* init/Makefile.am: Include notify.o from all tests.
* init/job.c (job_change_state, job_kill_process, job_start)
(job_stop): Use the new notify_job function name.
* init/event.c (event_queue_run): Use the new notify_event function
name.
* init/control.c (control_error_handler): Handle ECONNREFUSED now
that the process id is available to us.
* init/tests/test_control.c (test_error_handler): Make sure children
going away is handled properly.
* upstart/message.c (upstart_message_new): Store the process id in
the int_data message field.
* upstart/tests/test_message.c (test_new): Check the int_data field
is filled in.
* init/main.c (main): Guard against various things returning an error
that we weren't catching.
* init/tests/test_notify.c: Whitespace fix.
* init/control.c (control_watch_jobs, control_unwatch_jobs)
(control_watch_events, control_unwatch_events): Restore functionality
to subscribe and unsubscribe from job and event notifications.
* init/tests/test_control.c (test_watch_jobs, test_unwatch_jobs)
(test_watch_events, test_unwatch_events): Check that the subscription
and unsubscription messages work.
* init/Makefile.am (test_control_LDADD): Link to notify.o
* init/control.c: Drop unused include of upstart/errors.h
* init/notify.c: Move functions that handle subscription and
notification from control.c. Other than changing the names, we're
keeping the API the same for now; expect it to change later when we
add the ability to subscribe to individual jobs or events.
(notify_init): initialise the subscriptions list; we don't have a
separate send queue now that the control I/O is always asynchronous.
* init/notify.h: Moved notification enum, structure and prototypes
from control.h, changing the names so they match notify_* in the
process.
* init/Makefile.am (init_SOURCES): Build and link notify.c using
notify.h
(TESTS): Build the notify test suite binary.
(test_notify_SOURCES, test_notify_LDFLAGS, test_notify_LDADD): Details
for notify test suite binary.
* init/tests/test_notify.c: Rewrite test cases in the manner of
test_control.c so that we have one function for notify_job and
one for notify_event, each of which contains the child process that
receives the notification,
* init/control.c (control_open): Allow this to be called to obtain
the control socket, which means we can make it static.
* init/tests/test_control.c (test_open): Check that it works.
* init/control.c, init/control.h, init/tests/test_control.c: Move
functions that handle subscription and notification to new notify.c
(control_init): Drop completely, no need to maintain a send queue now
(control_open): Change to return an NihIo that uses the default
control watcher, and our error handler. Split socket opening into
(control_open_sock): which can be called from other functions.
(control_close): Use nih_io_close() to close the socket and free the
structure in one go.
(control_reopen): Close the open control socket and open it again
without destroying the NihIo structure, its queues or state.
(control_close_handler): Handle the control socket going away
(control_error_handler): Handle errors on the control socket,
including the connection refused error that indicates a client went
away.
(control_handle): Split this into a miriad of small functions with
a table to link them to the message type; this will make expanding
each message handler much easier in future.
* init/control.h: Update.
* init/tests/test_control.c: Rewrite test cases to check the new
handler functions; as a side-effect, this gets rid of the evil giant
child/parent functions in favour of one test function per handler
function.
* upstart/message.c (upstart_message_handle_using): Wrapper function
around upstart_message_handle that ensures all messages as passed to
a single function.
* upstart/message.h: Update.
* upstart/tests/test_message.c (test_handle_using): Make sure it
calls the single function.
2007-01-04 Scott James Remnant <scott@netsplit.com>
* upstart/message.c (upstart_message_reader): Handle any errors
that occurred while handling the message.
2007-01-02 Scott James Remnant <scott@netsplit.com>
* upstart/message.c (upstart_message_handle): Check that the name
argument is never NULL.
(upstart_message_reader): Simple message reader function that can
be associated with an I/O watch and handles each message received.
* upstart/message.h: Add prototype.
* upstart/tests/test_message.c (test_reader): Test the reader function.
* upstart/control.c: Rename to upstart/message.c
* upstart/control.h: Rename to upstart/message.h
* upstart/tests/test_control.c: Rename to upstart/tests/test_message.c
* upstart/libupstart.h: Update includes.
* upstart/wire.c: Include message.h
* upstart/wire.h: Update includes.
* upstart/tests/test_wire.c: Update includes.
* upstart/errors.h: Rename UPSTART_INVALID_MESSAGE to
UPSTART_MESSAGE_INVALID so that it's prefixed.
* upstart/Makefile.am (libupstart_la_SOURCES)
(upstartinclude_HEADERS, TESTS): Update filenames.
* upstart/control.c (upstart_message_new): New function that
creates an NihIoMessage directly from its arguments, which are a type
followed by a variable number of args depending on that type.
(upstart_message_handler): Function to find a handler function for
a particular message type and origin process.
(upstart_message_handle): New function that takes an NihIoMessage
and invokes a handler function with a variable number of args
depending on the message type.
(upstart_send_msg, upstart_send_msg_to, upstart_recv_msg): Drop these
functions, leave it up to the caller to decide whether to send and
receive the messages synchronously or asynchronously; now that the
capability is in nih_io_*.
* upstart/control.h (UpstartMsgType): Rename to UpstartMessageType.
(UpstartMessageHandler): Function with variable number of arguments
that handles a message received.
(UpstartMsg): Drop this structure entirely, we'll encode or decode
the wire format directly from or into a function call, rather than
use an intermediate structure to marshal it.
(UpstartMessage): New structure to make a table that can be passed
to upstart_message_handle to determine which handler should be called.
* upstart/tests/test_control.c: Test new behaviour.
* upstart/wire.c (upstart_push_header, upstart_pop_header): Change
structure name for type parameter.
* upstart/wire.h: Update.
* upstart/tests/test_wire.c: Update.
* configure.ac (AC_COPYRIGHT): Update copyright to 2007.
2006-12-29 Scott James Remnant <scott@netsplit.com>
* upstart/wire.c (upstart_write_int, upstart_write_unsigned)
(upstart_write_string, upstart_write_header, upstart_write_packv)
(upstart_write_pack): Rename to *_push_*
(upstart_read_int, upstart_read_unsigned, upstart_read_string)
(upstart_read_header, upstart_read_packv, upstart_read_pack): Rename
to *_pop_*.
All of the above modified to modify an NihIoMessage structure,
instead of trying to carry around buffers ourself.
* upstart/wire.h: Update to match above.
* upstart/tests/test_wire.c: Update all tests to match the above
changes.
2006-12-21 Scott James Remnant <scott@netsplit.com>
* upstart/wire.c (upstart_read_packv, upstart_write_packv): Change
nih_assert_notreached to nih_assert_not_reached.
* init/job.c (job_run_script): Open the NihIo structure in stream mode.
* logd/main.c (logging_watcher): Open the NihIo structure in
stream mode.
(logging_reader): Need to pass the length of the size_t as a pointer
so that it can be modified if less is read.
2006-12-17 Scott James Remnant <scott@netsplit.com>
* upstart/wire.c (upstart_write_packv, upstart_write_pack)
(upstart_read_packv, upstart_read_pack): Functions to write a pack
of different variables to the stream, or read them from it
* upstart/wire.h: Add prototypes.
* upstart/tests/test_wire.c (test_write_pack, test_read_pack):
Check we can read and write a pack of variables at once.
* upstart/wire.c (upstart_write_header, upstart_read_header): Drop
the version from the header, we'll just keep the protocol always
backwards compatible.
* upstart/wire.h: Update.
* upstart/tests/test_wire.c (test_write_header, test_read_header):
Check that everything works.
* upstart/wire.c (upstart_write_string, upstart_read_string):
Transmit the length as an unsigned, and use 0xffffffff to mean NULL
instead of zero so we can still transmit the empty string.
* upstart/wire.h: Update.
* upstart/tests/test_wire.c (test_write_string, test_read_string):
Tests for the functions to make sure the wire is at it should be.
* upstart/wire.c (upstart_read_str, upstart_write_str): Rename to
upstart_read_string and upstart_write_string.
* upstart/wire.h: Update.
* upstart/wire.c (upstart_write_unsigned, upstart_read_unsigned):
Functions to send unsigned values over the wire, which we'll use
to get a bit extra for the string lengths.
* upstart/wire.h: Update.
* upstart/tests/test_wire.c (test_write_unsigned)
(test_read_unsigned): Test the new functions.
* upstart/wire.c (upstart_write_ints, upstart_read_ints): Drop
these functions, we'll go with something far more generic and
useful.
* upstart/wire.h: Remove prototypes.
* upstart/wire.c (upstart_write_int, upstart_read_int): Transmit
integers as signed 32-bit values in network byte order.
* upstart/tests/test_wire.c (test_write_int, test_read_int): Test
the functions to make sure the wire is at it should be,
* upstart/control.c (upstart_read_int, upstart_write_int)
(upstart_read_ints, upstart_write_ints, upstart_read_str)
(upstart_write_str, upstart_read_header, upstart_write_header): Move
functions to new wire.c file.
* upstart/wire.c: Source file to hold wire protocol functions.
* upstart/wire.h: Prototypes.
* upstart/tests/test_wire.c: (empty) test suite.
* upstart/libupstart.h: Include wire.h
* upstart/Makefile.am (libupstart_la_SOURCES): Build and link wire.c
(upstartinclude_HEADERS): Install wire.h
(TESTS): Build and run wire test suite.
(test_wire_SOURCES, test_wire_LDFLAGS, test_wire_LDADD): Details for
wire test suite binary.
* upstart/control.c (MAGIC): Change to "upstart\n", the final
character was originally \0 and then was a " " for the 0.2 series.
* upstart/tests/test_control.c (test_recv_msg): Change to match.
2006-12-15 Scott James Remnant <scott@netsplit.com>
* util/initctl.c, compat/sysv/telinit.c, compat/sysv/shutdown.c:
Update all uses of the UpstartMsg structure to avoid the
intermediate union that no longer exists.
* init/control.c, init/tests/test_control.c: Update all uses of
the UpstartMsg structure to avoid the intermediate union that no
longer exists.
* upstart/control.h: Combine all the previous message structures
into just one that has all of the fields anyway.
* upstart/control.c, upstart/tests/test_control.c: Update all uses of
the UpstartMsg structure to avoid the intermediate union that no
longer exists.
* upstart/control.h (UPSTART_API_VERSION): Define API version macro
to be public.
* upstart/control.c (MSG_VERSION, upstart_send_msg_to): Replacing the
previous MSG_VERSION macro here.
* upstart/control.c (upstart_read_int, upstart_write_int)
(upstart_read_ints, upstart_write_ints, upstart_read_str)
(upstart_write_str, upstart_read_header, upstart_write_header):
New functions to replace the old "write a struct" protocol with
something a little more regimented and supportable.
(IOVEC_ADD, IOVEC_READ, WireHdr, WireJobPayload, WireJobStatusPayload)
(WireEventPayload): Remove these structures, use the functions
instead.
(upstart_send_msg_to): Call write functions intead of using macros,
this makes the code somewhat neater.
(upstart_recv_msg): Call read functions instead of using macros,
again making the code somewhat neater.
* upstart/tests/test_control.c (test_recv_msg): Change wire
tests to match new protocol, and thus actually work properly,
previously these were endian sensitive.
2006-12-14 Scott James Remnant <scott@netsplit.com>
* compat/sysv/shutdown.c (wall): Construct the wall message so that
we don't put \r into a po file; for some reason, gettext hates that
and bitches about it. Someone's confusing internationalisation with
operating system portability, I expect.
* util/man/initctl.8: Drop reference to start(8), as that's just
a symlink to initctl now.
* init/man/init.8: Link to initctl.
* compat/sysv/reboot.c (main): Clear up help text a little.
* HACKING: Correct some typos.
* configure.ac (AC_INIT): Correct bug reporting address.
2006-12-13 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.3.2
* NEWS: Update.
* util/initctl.c (print_job_status): Drop the newline from the
output.
2006-12-13 Alex Smith <alex@alex-smith.me.uk>
* util/initctl.c (print_job_status): Clean up initctl job status
output, which was badly converted from printf to nih_message.
2006-12-13 Scott James Remnant <scott@netsplit.com>
* compat/sysv/man/shutdown.8: Add missing documentation on the
format of TIME by copying it from --help output.
2006-12-13 Alex Smith <alex@alex-smith.me.uk>
* init/process.c (process_setup_console): Actually send output to
/dev/null instead of /dev/console, when CONSOLE_NONE.
2006-12-13 Scott James Remnant <scott@netsplit.com>
* Makefile.am (EXTRA_DIST): Distribute the nih ChangeLog as well.
* init/tests/test_job.c: Port to the new test framework.
* init/job.c (job_set_idle_event): Fix a slight memory leak,
repeated setting of the idle event never freed the previous one set.
2006-12-12 Scott James Remnant <scott@netsplit.com>
* init/tests/test_cfgfile.c: Port to the new test framework.
* init/tests/test_control.c: Port to the new test framework.
* init/init.supp: Suppress the list head allocated within control_init.
* init/control.c (control_watcher): Need to save the pid when we
get ECONNREFUSED, otherwise we lose it when we free the message.
* init/tests/test_process.c: Port to the new test framework.
* init/init.supp: Suppress the list head allocated within job_init.
* init/init.supp: Include a valgrind suppressions file.
* init/Makefile.am (EXTRA_DIST): Distribute the suppressions file.
* init/tests/test_event.c: Port to the new test framework.
* logd/Makefile.am, util/Makefile.am, compat/sys/Makefile.am
(AM_CPPFLAGS): Add -I$(srcdir), necessary for testing "programs"
that don't have usual library path semantics.
* upstart/tests/test_control.c: Port to the new test framework.
* upstart/control.c (upstart_free): Drop this function, while not
exposing libnih is a valiant effort, it already slips out because
of the error handling.
* upstart/tests/test_job.c: Add missing include.
* upstart/tests/test_job.c: Port to the new test framework.
(test_process_state_name): Check that this returns NULL.
* HACKING: Update location of download directory. Document
requirement that all code have test cases.
* logd/main.c (open_logging): Likewise.
* init/control.c (control_open): No need to set ENOMEM, errno is
always set anyway.
* configure.ac (AM_INIT_AUTOMAKE): Include nostdinc so we don't get
Automake's broken default includes.
* upstart/Makefile.am (DEFAULT_INCLUDES): Drop override now that
we don't need it.
(DEFS, INCLUDES): Replace these variables with the combined
(AM_CPPFLAGS): variable that declares everything.
* init/Makefile.am (DEFAULT_INCLUDES): Drop override now that
we don't need it.
(DEFS, INCLUDES): Replace these variables with the combined
(AM_CPPFLAGS): variable that declares everything.
* util/Makefile.am (DEFAULT_INCLUDES): Drop override now that
we don't need it.
(DEFS, INCLUDES): Replace these variables with the combined
(AM_CPPFLAGS): variable that declares everything.
* compat/sysv/Makefile.am (DEFAULT_INCLUDES): Drop override now that
we don't need it.
(DEFS, INCLUDES): Replace these variables with the combined
(AM_CPPFLAGS): variable that declares everything.
* logd/Makefile.am (DEFAULT_INCLUDES): Drop override now that
we don't need it.
(DEFS, INCLUDES): Replace these variables with the combined
(AM_CPPFLAGS): variable that declares everything.
2006-11-02 Scott James Remnant <scott@netsplit.com>
* util/initctl.c (start_action): Remove break calls which shouldn't
be there.
2006-10-18 Sean E. Russell <ser@ser1.net>
* init/main.c: Include sys/time.h
* init/cfgfile.c: Include sys/time.h and sys/resource.h
* init/job.c: Include sys/time.h and sys/resource.h
2006-10-17 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.3.1
* NEWS: Update.
* TODO: Update.
* configure.ac (AM_GNU_GETTEXT_VERSION): Quote version number.
* logd/Makefile.am (event.d/logd): Make the event.d sub-directory
in case we're building outside of the source tree.
* compat/sysv/runlevel.c (store): Don't break strict-aliasing rules
by avoiding dereferencing type-punned pointer. Answers on a
postcard, please.
2006-10-13 Scott James Remnant <scott@netsplit.com>
* util/initctl.c (start_action, emit_action): Add missing \n
* util/initctl.c: Rewrite using nih_command_parser.
* util/man/initctl.8: Improve.
* util/start.c: Remove, replaced by initctl.
* util/man/start.8: Remove, replaced by initctl.
* util/Makefile.am (sbin_PROGRAMS): Drop start, now just a symlink
to initctl.
(dist_man_MANS): Drop start.8, now a symlink to initctl.8
(install-exec-hook): Make symlinks to initctl, add start
(install-data-hook): Make symlinks to initctl.8, add start.8
* initctl: Rename to util again, I don't want a separate directory
for every single little tool; and we'll be shipping more than just
initctl (e.g. a non-compat reboot).
* configure.ac (AC_CONFIG_FILES): Make util/Makefile instead of
initctl/Makefile.
* Makefile.am (SUBDIRS): Descend into util, not initctl.
* compat/sysv/reboot.c: Remove long options where they didn't exist
before. Write help text.
* compat/sysv/man/reboot.8: Update.
* init/main.c (main): Formatting.
* logd/main.c (main): Formatting.
* logd/man/logd.8: Formatting.
* compat/sysv/runlevel.c (main): Formatting.
* compat/sysv/telinit.c (main): Formatting.
* compat/sysv/man/shutdown.8: Remove long options.
* compat/sysv/shutdown.c: Remove -e/--event, it has no place in a
compatibility tool. Get rid of long options that never existed
before. Specify help text to describe the options.
* compat/sysv/man/shutdown.8: Spruce up a bit.
* compat/sysv/telinit.c (main): Set help text to list the valid
runlevels.
* compat/sysv/man/telinit.8: Refine the notes to mention runlevel(8).
* compat/sysv/runlevel.c (main): Make the help text describe the
options, rather than the behaviour.
* compat/sysv/man/runlevel.8: Flesh out a little more.
* configure.ac (AC_INIT): Change bug reporting address to the
mailing list, since Launchpad doesn't accept random bugs without
accounts and complicated control messages.
* init/main.c, logd/main.c: Add a period to the synopsis.
* init/main.c (main): Set the synopsis, and direct people to look
at telinit in the --help output.
* init/man/init.8: Flesh this out a little more, still a lot of
explaining to do about jobs and events, but we'll wait until we've
changed that code before documentating the behaviour.
* logd/main.c (main): Correct help text to describe the options,
rather than what the program does. As per standard style.
Don't become a daemon until the logging socket is open, and make
that exclusive with waiting for SIGCONT.
* logd/man/logd.8: Write some more extensive documentation,
including describing the startup interlock and the socket protocol.
* TODO: Plan to get rid of the signal interlock from logd.
2006-10-12 Scott James Remnant <scott@netsplit.com>
* configure.ac: Expand AC_GNU_SOURCE so we get _GNU_SOURCE and so
that gettext doesn't complain.
(AM_GNU_GETTEXT_VERSION): Increase to 0.15
(AC_PREREQ): Increase to 2.60
* HACKING: Update autoconf and gettext requirements.
2006-10-11 Scott James Remnant <scott@netsplit.com>
* init/control.c (control_init): Pass NULL to nih_list_new.
Clarify list item types.
* init/event.c (event_init): Pass NULL to nih_list_new.
* init/job.c (job_init): Pass NULL to nih_list_new.
* init/main.c: Change nih_signal_add_callback to nih_signal_add_handler
and NihSignalCb to NihSignalHandler.
* init/cfgfile.c, init/cfgfile.h, init/control.c, init/control.h,
init/event.c, init/event.h, init/job.c, init/job.h, init/main.c,
init/process.c: Clean up documentation strings and parent pointer
types.
* compat/sysv/shutdown.c: Change nih_signal_add_callback to
nih_signal_add_handler.
* compat/sysv/reboot.c: Set synopsis text depending on command
used (probably should use nih_command_parser?)
* compat/sysv/runlevel.c: Set synopsis and help text, and correct
usage.
* compat/sysv/shutdown.c: Set synopsis text.
* compat/sysv/telinit.c: Set synopsis text.
* compat/sysv/runlevel.c, compat/sysv/shutdown.c: Clean up
documentation strings.
* logd/main.c: Set synopsis and help text.
* logd/main.c: Clean up documentation strings.
Change nih_signal_add_callback to nih_signal_add_handler.
* upstart/control.c, upstart/control.h, upstart/job.c: Clean up
documentation strings and correct parent pointer type.
* HACKING: Detail function documentation requirement and format.
2006-10-10 Scott James Remnant <scott@netsplit.com>
* event.d/logd.in: Move to logd/event.d
* event.d/Makefile.am: Remove
* logd/Makefile.am: Create the logd job definition and install
* Makefile.am (SUBDIRS): event.d directory has been removed.
* configure.ac (AC_CONFIG_FILES): No longer make event.d/Makefile
* configure.ac: Check for --enable-compat, default to sysv if given
or no compat if not given.
* compat/sysv/Makefile.am: Don't build binaries or install manpages
unless COMPAT_SYSV is defined.
2006-10-06 Scott James Remnant <scott@netsplit.com>
* doc/upstart-logo.svg: Include the logo Alexandre designed.
* doc/Makefile.am (EXTRA_DIST): Ship the logo in the tarball.
* Makefile.am (SUBDIRS): Install under doc
* configure.ac: Generate doc/Makefile
* AUTHORS: Ensure he's credited fully.
2006-09-27 Scott James Remnant <scott@netsplit.com>
* event.d/Makefile.am (do_subst): Eliminate duplicate /s
* man/init.8: Move to init/man
* init/Makefile.am: Update to install man page.
* man/logd.8: Move to logd/man
* logd/Makefile.am: Update to install man page.
* man/initctl.8, man/start.8: Move to initctl/man
* initctl/Makefile.am: Update to install man pages.
* man/reboot.8, man/runlevel.8, man/shutdown.8, man/telinit.8:
Move to compat/sysv/man
* compat/sysv/Makefile.am: Update to install man pages.
* man/Makefile.am: Remove
* configure.ac (AC_CONFIG_FILES): Remove man/Makefile
* Makefile.am (SUBDIRS): Don't build in man
* util: Rename to initctl
* configure.ac (AC_CONFIG_FILES): Update.
* Makefile.am (SUBDIRS): Update.
* util/reboot.c: Move to compat/sysv
* util/shutdown.c: Move to compat/sysv
* util/Makefile.am: Update.
* compat/sysv/Makefile.am: Update.
* configure.ac: Replace macros with single call to NIH_INIT.
Bump version to 0.3.0 to begin new development cycle.
2006-09-21 Scott James Remnant <scott@netsplit.com>
* logd/main.c: Revert the change that logged to the console, in
practice this doesn't work so well. I want to get rid of logd
in the long term, or at least just have it as a simple logging
proxy, so giving it features seems wrong.
2006-09-20 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.2.8
* NEWS: Updated.
* logd/main.c (main): Check the kernel command-line for "quiet"
(line_reader): Write to console unless silent or a daemon
* man/Makefile.am (dist_man_MANS): Drop sulogin.8
* man/sulogin.8: Drop, we don't include an sulogin
2006-09-19 Michael Biebl <mbiebl@gmail.com>
* event.d/Makefile.am (logd): Drop $(srcdir)
* init/Makefile.am (init_SOURCES): Distribute paths.h
2006-09-18 Michael Biebl <mbiebl@gmail.com>
* configure.ac: Check for sys/inotify.h
2006-09-18 Scott James Remnant <scott@netsplit.com>
* util/shutdown.c (warning_message): Adjust method of constructing
the message to not confuse poor translators who think \r and \n are
the same thing!
2006-09-14 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_change_state): Catch runaway respawns when we
enter the running state, so we catch stop/start loops too.
* init/tests/test_job.c (test_change_state): Update test.
* event.d/logd: Rename to logd.in
* event.d/logd.in: Replace /sbin with @sbindir@ so we can transform
* event.d/Makefile.am: Generate logd from logd.in
* util/reboot.c: Don't hardcode the location of /sbin/shutdown
* util/Makefile.am (DEFS): Use autoconf to seed it
* util/shutdown.c (sysvinit_shutdown): Don't hardcode the location
of /dev/initctl
* init/paths.h: Create a new configuration file that can contain
all of the path definitions, and in particular, allow them to be
overidden elsewhere.
* init/Makefile.am (DEFS): Override definitions of CFG_DIR and
TELINIT using autoconf
* init/main.c: Include paths.h. Don't hardcode location of telinit
* init/job.c: Include paths.h
* init/process.c: Include paths.h
* init/process.h: Remove definitions from here.
* configure.ac: Bump version to 0.2.7
2006-09-13 Scott James Remnant <scott@netsplit.com>
* NEWS: Updated.
* TODO: More TODO.
2006-09-10 Scott James Remnant <scott@netsplit.com>
* util/reboot.c (main): Don't give -H with "halt".
2006-09-09 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.2.6
* NEWS: Update.
* TODO: Update.
* upstart/control.c (upstart_send_msg_to, upstart_recv_msg): Change
the magic to be the package string.
* upstart/tests/test_control.c (test_recv_msg): Update tests.
* util/initctl.c (main): Set the usage string.
* util/shutdown.c (main): Set the usage string.
* util/start.c (main): Set the usage string.
* compat/sysv/runlevel.c (main): Set the usage string.
* compat/sysv/telinit.c (main): Set the usage string.
* man/Makefile.am: Use install-data-hook and $(man8dir)
* util/Makefile.am: Also use install-exec-hook
* Makefile.am (SUBDIRS): Install contents of the man directory
* configure.ac (AC_CONFIG_FILES): Generate man/Makefile
* man/Makefile.am: Install manpages in the appropriate places.
* man/init.8, man/logd.8, man/initctl.8, man/reboot.8,
* man/shutdown.8, man/start.8, man/sulogin.8, man/runlevel.8,
* man/telinit.8: Include some basic manpages so we at least have
some level of documentation.
* init/job.c (job_child_reaper): Don't check the exit status of
a respawning job if the goal is to stop it.
* compat/sysv/telinit.c (main): Generate events rather than
starting and stopping jobs directly, the events are named
"runlevel-X". 0, 1, 6 and s/S are shutdown events.
* logd/main.c (main): Raise SIGSTOP before entering the main loop.
* init/main.c (main): Interlock with logd.
* event.d/logd: Should not be a console owner, but should stop
on shutdown.
* init/process.c (process_setup_console): Revert part of the previous
change, should just output to /dev/null if we don't have logd.
* configure.ac: Bump version to 0.2.5
* init/main.c (main): Start the logd job if it exists.
* init/process.c (process_setup_console): Ignore ECONNREFUSED as
that just means that logd isn't around, handle errors by falling
back to opening the console.
* init/process.c (process_setup_console): Implement handling for
CONSOLE_LOGGED and generally clean up the other handling.
* init/process.h: Update.
* init/main.c (main): Pass NULL for the job to setup console.
* TODO: Update.
* logd/main.c: Implement the logging daemon, it accepts connections
on a unix stream socket with the abstract name
"/com/ubuntu/upstart/logd", expects the length of the name and the
name to follow; then sequences of lines which are logged to
/var/log/boot, or memory until that file can be opened.
2006-09-08 Scott James Remnant <scott@netsplit.com>
* util/shutdown.c (event_setter): Change the event names to
distinguish between "shutdown -h" and "shutdown -h -H".
* init/job.c (job_handle_event): Allow jobs to react to their own
events, this is how we'll do respawn eventually.
* init/tests/test_job.c (test_handle_event): Remove test.
* init/main.c (cad_handler, kbd_handler): Generate the new event
names.
* init/event.h (CTRLALTDEL_EVENT, KBDREQUEST_EVENT): Add definitions
of these event names, change the ctrlaltdel event to just that.
* logd/main.c (main): Add the code to daemonise, etc.
2006-09-07 Scott James Remnant <scott@netsplit.com>
* TODO: Long discussion today on #upstart, many improvements to the
job and event model that make it more elegant.
* AUTHORS: Include a list of thanks.
* util/shutdown.c (shutdown_now): If we get ECONNREFUSED when we
try and send the shutdown event to init, it probably means we're
still in sysvinit. So try that instead.
(sysvinit_shutdown): Function to send a hand-crafted runlevel
change message across /dev/initctl.
* util/initctl.c (main): Add a shutdown command that takes an
arbitrary event name to be issued after "shutdown". You'll
nearly always want the /sbin/shutdown tool instead.
* init/job.c (job_detect_idle): Only generate the stalled event
if at least one job handles it in its start_events list.
* init/tests/test_job.c (test_detect_idle): Make sure that works.
* init/event.h (STARTUP_EVENT, SHUTDOWN_EVENT, STALLED_EVENT):
Macros to define the standard event names.
* init/main.c (main): Use STARTUP_EVENT macro instead of "startup"
* init/control.c (control_handle): Use SHUTDOWN_EVENT macro
instead of "shutdown".
* init/job.c (job_detect_idle): Use STALLED_EVENT macro instead
of "stalled".
* init/job.c (job_detect_idle): Add some log messages for when we
detect the idle or stalled states.
(job_kill_process, job_kill_timer): Increase log verbosity.
* init/event.c (event_queue_run): Log which events we're handling
if --debug is given.
* compat/sysv/telinit.c (main): Send a shutdown command when
requesting to enter runlevel 0 or runlevel 6, likewise for
runlevel 1, s or S which all run "rc1" not "rcS".
* init/main.c (main): When called directory (pid != 1) try and
run telinit before complaining that we're not init. Make sure
errors aren't lost.
2006-09-04 Johan Kiviniemi <johan@kiviniemi.name>
* upstart/control.c (upstart_addr): Replace use of __builtin_offsetof
with offsetof.
* upstart/tests/test_control.c (test_recv_msg): Likewise.
2006-09-04 Scott James Remnant <scott@netsplit.com>
* util/shutdown.c (main): Exit normally after sending the warning
message if -k is given.
2006-09-01 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.2.2
* NEWS: Update.
* configure.ac: Bump version to 0.2.1
* init/process.c (process_setup_console): Ensure that the console
is always initialised to at least /dev/null
* init/job.c (job_change_state): Initialise event to NULL.
* init/event.c (event_read_state): Don't mask initialisation of
other variable.
* init/cfgfile.c (cfg_job_stanza, cfg_parse_script, cfg_next_token):
Print lineno using %zi not %d
* compat/sysv/runlevel.c (store): Cast pointer type of timeval.
* init/main.c: Move the kernel headers include beneath the C
library ones, so that compilation doesn't fail on !i386.
* util/reboot.c: Likewise.
* init/main.c (term_handler): Close the control connection if we
re-exec init, otherwise it won't be able to bind. Drop debugging.
* init/main.c (term_handler): It always helps if we dup2 the
right file descriptor.
* init/main.c: Use the TERM signal instead of USR1, as old init
used that for something else. Also rather than passing across
file descriptor numbers, use a fixed descriptor and just pass
"--restart". When we get that option we need to unmask signals
otherwise we sit there looking like a lemon.
* init/job.c (job_change_state): Don't free the event unless we
generate one.
* NEWS: Update.
* init/cfgfile.c (cfg_watcher): Ignore any file with '.' or '~'
* TODO: Update.
* init/main.c (main): Parse command-line arguments, specifically
look for --state-fd which we'll use for reexec. Don't do a couple
of things if we're passed this.
(read_state): Parse the line-buffered state.
* init/job.c (job_read_state, job_write_state): Job state
serialisation so that we can re-exec ourselves.
* init/job.h: Update.
* init/tests/test_job.c: Test the serialisation.
* init/event.c (event_read_state, event_write_state): And similar
functions for serialising the event queue.
* init/event.h: Update.
* init/tests/test_event.c: Test the serialisation.
* init/cfgfile.c (cfg_read_job): Fix a bug, need to subtract current
time to get due time.
* upstart/job.c (job_goal_from_name, job_state_from_name)
(process_state_from_name): Add opposite numbers that convert a
string back into an enumeration.
* upstart/job.h: Update.
* upstart/tests/test_job.c: Test the new functions.
2006-08-31 Scott James Remnant <scott@netsplit.com>
* init/job.h (Job): Add respawn_limit, respawn_interval,
respawn_count and respawn_time members so that we can keep track of
runaway processes.
* init/job.c (job_catch_runaway): Increment the respawn_count
within respawn_interval, or reset it if we go over.
(job_new): Initialise respawn_limit and respawn_interval to sensible
defaults.
* init/tests/test_job.c (test_new): Check the defaults are set.
(test_change_state): Check the respawning code works.
* init/cfgfile.c (cfg_job_stanza): Parse the "respawn limit" stanza.
* init/tests/test_cfgfile.c (test_read_job): Test the new stanza.
* init/process.c (process_setup_console): Remove the console reset
code, it tends to just crash X and seems to do nothing interesting.
* init/main.c (reset_console): Instead put it here and just do it
on startup.
* configure.ac: Bump version to 0.2.0
* util/Makefile.am (install-exec-local): Create symbolic links,
not hard links.
* init/main.c: Can't catch STOP.
* util/reboot.c: Pause init while shutting down or rebooting.
* init/main.c (stop_handler): Catch STOP/TSTP and CONT.
* init/event.c (event_queue_run): Don't run the event queue while
paused.
* init/job.c (job_detect_idle): Don't detect idle jobs while paused.
* util/reboot.c: if we get the -w argument ("only write to wtmp")
we need to exit, and not behave as halt normally would.
* compat/sysv/runlevel.c (main): Add missing newline.
* compat/sysv/telinit.c (main): And here too.
* init/main.c (main): Check for idle after the startup event queue
has been run, otherwise we may just sit there.
* compat/sysv/Makefile.am (sbin_PROGRAMS): Build and install telinit
(telinit_SOURCES, telinit_LDFLAGS, telinit_LDADD): Details for
telinit binary.
* compat/sysv/telinit.c: Trivial telinit program that just runs
the appropriate rcX job.
* compat/sysv/runlevel.c (main): Suggest help on illegal runlevel.
* util/Makefile.am: Tidy up.
* configure.ac (AC_CONFIG_FILES): Create compat/sysv/Makefile
* Makefile.am (SUBDIRS): Build things found in compat/sysv
* compat/sysv/Makefile.am (sbin_PROGRAMS): Build and install runlevel
(runlevel_SOURCES, runlevel_LDFLAGS, runlevel_LDADD): Details for
runlevel binary.
* compat/sysv/runlevel.c: Helper to store and retrieve the current
"runlevel" from utmp/wtmp; as well as the reboot time.
* init/main.c (main): Drop debugging set.
* init/job.c (job_change_state): As well as the job/state events,
send the job event when a service is running or a task is stopping.
* init/tests/test_job.c (test_change_state): Check the events get
sent properly.
* util/start.c: Write a simple utility to start, stop, or query
the status of the named jobs.
* util/Makefile.am (sbin_PROGRAMS): Build and install start
(start_SOURCES, start_LDFLAGS, start_LDADD): Details for start
(install-exec-local): Also install as stop and status.
* util/reboot.c (main): Drop the debugging set.
* init/cfgfile.c (cfg_job_stanza): Correct nih_alloc error.
* init/process.c (process_setup_environment): Guard memory alloc.
* init/job.c (job_set_idle_event): Likewise.
(job_change_state): And here too.
(job_run_command): Likewise.
* init/control.c (control_send): Likewise.
* init/cfgfile.c: And throughout this file.
* upstart/control.c (upstart_recv_msg): And once here too.
* upstart/control.h: Abolish the separate halt, reboot and poweroff
messages and replace with a single shutdown message that takes
an event name (for the idle event issued afterwards).
* upstart/control.c (upstart_send_msg_to, upstart_recv_msg): Handle
the new shutdown event type by just treating it as an event.
* upstart/tests/test_control.c (test_messages): Update tests.
* init/job.c (job_set_idle_event): Store a copy of the idle event
name.
* init/control.c (control_send): Copy the shutdown event name.
(control_handle): Replace individual handling with the new
single event.
* init/tests/test_control.c (test_watcher): Update.
* util/initctl.c: Drop handling for things that shutdown does now.
* util/shutdown.c: Send the UPSTART_SHUTDOWN event and let the user
specify anything they want, just give defaults.
This is quite a big change and abolishes level events entirely,
along with the event history. We now just treat events as a
transient queue of strings that go past, may cause things to change,
but are otherwise forgotten. This turns out to be much easier to
understand and has no real loss of power.
* init/event.c: Vastly simplify; gone are the separate notions of
edge and level events, instead we just treat them as one-shot
things that go past and are forgotten about.
* init/event.h (Event): Remove value member.
Update prototypes.
* init/tests/test_event.c: Update.
* init/job.c (job_change_state): Change the event pattern to be
one that includes the job name and a description of the transition
instead of the new state.
(job_detect_idle): Call event_queue rather than event_queue_edge.
* init/tests/test_job.c: Update.
* init/cfgfile.c (cfg_job_stanza): Drop "when" and "while".
* init/tests/test_cfgfile.c (test_read_job): Drop mentions of
"when" and "while".
* init/control.c (control_send, control_handle): Drop cases for
level events.
(control_handle_event): Don't include a level in the event.
* init/tests/test_control.c: Update
* init/main.c: Call event_queue rather than event_queue_edge.
* upstart/control.c (upstart_send_msg_to, upstart_recv_msg): Change
event handling so that only a name is read.
* upstart/control.h: Remove value/level event structures.
* upstart/tests/test_control.c (test_messages): Update.
* upstart/job.c (process_state_name): Not used for events, adjust
documentation so it doesn't lie.
* util/initctl.c (main): Drop the set function, simplify trigger.
* util/shutdown.c (shutdown_now): Call UPSTART_EVENT_QUEUE for
shutdown into maintenance mode.
* init/control.c (control_handle): Place a message in the syslog
before halting, powering off or rebooting.
* util/shutdown.c: Adjust so that the warning message is sent out
if shutdown is immediate, and when it actually happens. Include
the hostname as wall does.
2006-08-30 Scott James Remnant <scott@netsplit.com>
* TODO: Update.
* util/shutdown.c: Implement shutdown utility along the same lines
as the sysvinit one, but with rather different code.
* util/initctl.c (main): Call setuid on the effective user id so
that we can be made setuid root and executable by a special group.
* util/reboot.c (main): Likewise.
* util/initctl.c (main): Check the effective rather than the real
user id, if we're effectively root, that's good enough.
* util/reboot.c: Implement reboot/halt/poweroff utility.
* util/Makefile.am (sbin_PROGRAMS): Build and install reboot
(reboot_SOURCES, reboot_LDFLAGS, reboot_LDADD): Details for reboot
(install-exec-local): Create hardlinks to reboot for halt and poweroff.
2006-08-29 Scott James Remnant <scott@netsplit.com>
* init/main.c (main): Actually run the idle-detect function.
* init/job.c (job_detect_idle): Interrupt the main loop, otherwise
we may end up waiting for a signal before we process the event
we just issued.
2006-08-27 Scott James Remnant <scott@netsplit.com>
* util/shutdown.c: Template main function.
* util/Makefile.am (sbin_PROGRAMS): Build and install the
shutdown binary.
(shutdown_SOURCES, shutdown_LDFLAGS, shutdown_LDADD): Details for
the shutdown binary
* util/initctl.c (main): Add commands for halt, poweroff and reboot.
* init/event.c (event_queue_run): Remove the parameters.
* init/event.h: Update.
* init/main.c (main): Update.
* init/tests/test_control.c (test_watcher): Update.
* init/tests/test_job.c (test_detect_idle): Update.
* upstart/control.c (upstart_send_msg_to, upstart_recv_msg): Deal
with halting, rebooting and powering off; or at least the appropriate
messages.
* upstart/control.h: Add control message structures for halting,
powering off and rebooting the machine.
* upstart/tests/test_control.c (test_messages): Run the tests.
* init/control.c (control_handle): Add handling for halt, power off
and reboot that issue the shutdown event and arrange for the halt,
poweroff or reboot to be issued the next time the system is idle.
* init/tests/test_control.c (test_watcher): Test the events.
* TODO: Update.
* init/job.c (job_detect_idle): Function to detect when the system is
stalled or idle.
* init/job.h: Update
* init/tests/test_job.c (test_detect_idle): Test the new function.
* util/initctl.c (main): Handle the list command.
* TODO: Update.
* upstart/control.c (WireJobStatusPayload): add description to the
job status payload.
(upstart_send_msg_to, upstart_recv_msg): Send and receieve the
description over the wire.
* upstart/control.h (UpstartJobStatusMsg): add a description field
* upstart/tests/test_control.c: Update test cases.
* init/control.c (control_handle): Include the job description in
the message.
(control_send): Copy the description when we put the message on
the queue.
(control_handle_job): Copy the description here too
* init/tests/test_control.c: Update test cases.
* init/job.c (job_list): Add a function to return the job list.
* init/job.h: Update.
* init/control.c (control_handle): Handle the JOB_LIST message
by sending back a list of job status messages followed by the
JOB_LIST_END message.
* init/tests/test_control.c (test_watcher_child): Check the
JOB_LIST message works properly.
* upstart/control.c (upstart_send_msg_to, upstart_recv_msg): Handle
the JOB_LIST and JOB_LIST_END messages which have no payload.
* upstart/control.h: Add enums and structures for job list messages.
* upstart/tests/test_control.c (test_messages): Update tests.
* init/main.c (main): Check that we're both uid and process #1
* init/main.c (main): Stop handling SIGTERM, we never want people
to kill init. Handle SIGINT and SIGWINCH through the ordinary
handler and SIGSEGV through a direct handler.
(segv_handler): Write a sensible core dump handler, we use a child
to dump core while we carry on in the parent hopefully stepping over
the bad instruction.
(cad_handler): Generate the control-alt-delete event.
(kbd_handler): Generate the kbdrequest event.
2006-08-25 Scott James Remnant <scott@netsplit.com>
* configure.ac: Bump version to 0.1.2
* NEWS: Update.
* TODO: Update.
* init/process.c (process_setup_environment): Inherit the PATH
and TERM environment variables from the init process, so the
console works properly.
* init/process.h (PATH): Declare a default value for this variable
* init/main.c (main): Set the value of PATH to the default.
* init/tests/test_process.c (child): Update test case.
* NEWS: Update.
* configure.ac: Bump version to 0.1.1
2006-08-24 Scott James Remnant <scott@netsplit.com>
* init/cfgfile.h (CFG_DIR): Change configuration directory to
/etc/event.d -- it's not been used by anyone, but is similar to
other directories that have which is a good precedent.
* event.d/Makefile.am (eventdir, dist_event_DATA): Install files
into the new directory name.
* Makefile.am (SUBDIRS): Rename sub directory
* configure.ac (AC_CONFIG_FILES): Rename generated Makefile
* init/Makefile.am (DEFAULT_INCLUDES): Set to include the right
directories so out of tree builds work.
* logd/Makefile.am (DEFAULT_INCLUDES): Set to include the right
directories so out of tree builds work.
* upstart/Makefile.am (DEFAULT_INCLUDES): Set to include the right
directories so out of tree builds work.
(upstartinclude_HEADERS): Install errors.h
* util/Makefile.am (DEFAULT_INCLUDES): Set to include the right
directories so out of tree builds work.
* Makefile.am (SUBDIRS): Add m4 to the list
* configure.ac (AC_CONFIG_FILES): Generate m4/Makefile
* upstart/Makefile.am (upstartinclude_HEADERS): Add errors.h
* upstart/control.c (upstart_open):
* init/control.c (control_open): Raise the error before
performing other actions so errno is not lost.
* TODO: Update.o
* init/cfgfile.c (cfg_next_token): Don't count quote characters
unless we're actually planning to dequote the file, otherwise we
end up allocating short.
* init/control.c (control_close): Free the io_watch using list_free
in case a destructor has been set.
* init/tests/test_control.c: Initialise the type of the message, and
free job correctly.
* upstart/tests/test_control.c: Fix overwrite of buffer.
* init/tests/test_job.c: Clean up not-freed job.
2006-08-23 Scott James Remnant <scott@netsplit.com>
* init/tests/test_event.c: free the entry allocated and initialise
the return values.
* init/cfgfile.c (cfg_skip_token): Drop this function; we'll
make sure *pos is pointing at the start of the thing we want
to parse, not the first token. Update the other functions
accordingly.
(cfg_read_job): Implement function to look over a job file and
parse all of the stanzas that are found. Also sanity checks the
job afterwards and deals with reloading existing jobs.
(cfg_job_stanza): Function that parses an individual stanza,
calling out to the other parse functions; this is the main config
file parser!
(cfg_parse_args, cfg_parse_command): Drop requirement that filename
and lineno be passed, so we can be called to reparse arguments after
we've already done so.
(cfg_parse_script): Remove requirement that it be called at the
start of the entire stanza, and instead at the start of the script.
When hitting EOF, return the script so far, not NULL.
(cfg_parse_args): Correct bug where we didn't check sufficient
characters while skipping whitespace.
(cfg_next_token): Correct bug where we didn't copy the character
after a slash into the text, instead of just not copying the slash.
Adjust line numbers to match the fact that it's zero based now.
* init/cfgfile.h: Define prototype.
* init/tests/test_cfgfile.c (test_read_job): Pretty thoroughly
test the config file parser code.
2006-08-22 Scott James Remnant <scott@netsplit.com>
* init/cfgfile.c (cfg_tokenise): Rename to cfg_next_token.
(cfg_skip_token): Code to skip whitespace, token and whitespace.
(cfg_parse_args): Function to parse an argument list.
(cfg_next_token): Extend to support the removal of quotes and
slashes from the token.
* init/cfgfile.c (cfg_parse_script): Pass filename and lineno and
increment the latter as we go.
(cfg_script_end): Pass and increment lineno.
* init/cfgfile.c: Correct a missing semi-colon in prototypes.
(cfg_parse_command): Function to parse any stanza that requires
a command and arguments list, e.g. exec/respawn/daemon. We don't
want to require that the list be quoted, etc. and do want to allow
it to be folded over lines.
(cfg_tokenise): Function used by the above to tokenise the file,
handling things like \, quoted strings and newlines, etc. Can be
used both to determine the length of the token and to copy it.
* init/cfgfile.c (cfg_read_script): Rename to cfg_parse_script.
* init/cfgfile.c (cfg_read_script): Function to parse a script
fragment ("foo script\n....end script\n") from the job file, which
is the most complex form we can find. Write it assuming the file is
in a character array which may not be NULL terminated (ie. a mmap'd
file).
(cfg_script_end): Used by the above to detect the end of the
fragment.
* init/cfgfile.h: Empty header file.
* init/Makefile.am (init_SOURCES): Build and link cfgfile.c
using the cfgfile.h header
(TESTS): Build and run the config file test cases.
(test_cfgfile_SOURCES, test_cfgfile_LDFLAGS, test_cfgfile_LDADD):
Details for config file test case binary.
* init/main.c (main): Remove the calls to the unfinished config
file code.
2006-08-21 Scott James Remnant <scott@netsplit.com>
* init/main.c: Add missing include for unistd.h
* init/process.c (process_setup_console): Drop use of job.
* util/initctl.c (main): Check that we're run as root.
* init/main.c (main): Write the main function
* init/event.c (event_queue_cb): Rename to event_queue_run.
* init/event.h: Update.
* init/process.c (process_setup_console): Become an exported
function that includes the code to reset a console.
2006-08-19 Scott James Remnant <scott@netsplit.com>
* logd/main.c (main): Write the basic main function.
* util/initctl.c (main): Fill in the details to give us a basic
test client.
* TODO: Update.
* util/initctl.c (main): Provide the most basic main function.
* util/Makefile.am (sbin_PROGRAMS): Build the initctl binary
* Makefile.am (SUBDIRS): Build the utilities.
* configure.ac (AC_CONFIG_FILES): Generate the util Makefile.
2006-08-18 Scott James Remnant <scott@netsplit.com>
* init/Makefile.am (test_job_LDADD): Remove the duplicate link.
* TODO: Update.
* init/job.c (job_handle_child): Rename to job_child_reaper.
* init/job.h: Update.
* init/tests/test_job.c: Update function names.
* init/control.c (control_cb): Rename to control_watcher
* init/tests/test_control.c: Update function names.
* TODO: Update.
* Makefile.am (SUBDIRS): Install the rc.d files.
* configure.ac (AC_CONFIG_FILES): Generate the rc.d Makefile.
* rc.d/Makefile.am (rcdir): Define rcdir to be /etc/rc.d
(dist_rc_DATA): Install the logd file into that directory.
* rc.d/logd: Write a simple service definition for the log daemon,
this saves us hardcoding any information about it into init; it'll
just need to know the name.
* Makefile.am (SUBDIRS): Build the logd daemon
* configure.ac (AC_CONFIG_FILES): Generate the logd Makefile.
* logd/Makefile.am (sbin_PROGRAMS): Install the logd binary into
the sbin directory by default.
(logd_SOURCES): Build and link main.c
* logd/main.c (main): Add basic main function for testing purposes.
2006-08-16 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_start): Ignore self-dependencies; over-document
why the dependency event prodding has a surprise in its tail.
(job_change_state): Move the job_release_depends call to here.
* init/event.c (event_queue_cb): Add event consumer/dispatcher.
* init/event.h: Update.
* init/control.c (control_send): Make the event code clearer.
(control_handle): Handle the changed event semantics.
(control_handle_event): Issue the new event type.
* init/tests/test_control.c: Update tests.
* upstart/control.c (upstart_send_msg_to, upstart_recv_msg): Adjust
marshal code to match.
* upstart/control.h: Update all structures appropriately to the
previous changes.
* upstart/tests/test_control.c: Update.
* init/job.c (job_change_state): Change call to event_trigger_level
to event_queue_level.
* init/event.c (event_trigger_edge, event_trigger_level): Place
the event on the event_queue rather than directly triggering it.
Rename to event_queue_edge and event_queue_level respectively.
* init/event.h: Update.
* init/tests/test_event.c: Update test cases.
* init/job.c (job_handle_event): Add another sanity check, jobs
should not be able to react to their own events; that's just silly.
* init/tests/test_job.c (test_handle_event): Check that the new
condition does the right thing.
* init/job.c (job_change_state): Make it illegal for a job to exist
without either a command or script or both. This is for sanity
reasons, allowing no primary process makes no sense and can lead
to event loops if someone is feeling nefarious.
* init/tests/test_job.c (test_change_state): Drop test on behaviour
we've just outlawed.
* init/job.c (job_start): Only announce the change if we're still
in the waiting state, we could have moved on to running already.
* init/job.c (job_start): If holding the job, at least announce
the goal change to subscribed clients.
* TODO: Update.
* init/job.c (job_start): Check for dependencies before starting
the process, if we have any that aren't running we stay in waiting
until they are. Any that aren't even starting get poked with a
dependency event to see whether that wakes them up.
* init/tests/test_job.c (test_start): Test paths through new
dependency code.
* init/job.c (job_run_process): Once we've got an active process
in the running state, release our dependencies.
* init/job.c (job_release_depends): Function to release any waiting
dependencies on the given job.
* init/job.h: Update.
* init/tests/test_job.c (test_release_depends): Test the behaviour
of the function on its own.
* init/job.h (Job): Add depends list field
(JobName): New structure to hold the name of a job.
* init/job.c (job_new): Initialise the depends list.
* init/tests/test_job.c (test_new): Make sure the depends list is
initialised properly.
* init/job.c (job_next_state): Return JOB_STARTING if we're in
JOB_WAITING and the goal is JOB_START. This is only called when
there's some change, and I don't want to hard-code the goal there.
(job_start): Don't hardcode JOB_STARTING, instead just use the next
state.
* init/tests/test_job.c (test_next_state): Adjust test case.
* init/control.c (control_subscribe): Allow the current
subscription to be found by passing NOTIFY_NONE.
(control_handle): Don't remove an existing subscription to jobs,
a GUI will probably want a permanent one to keep the status up to
date.
* init/job.c (job_kill_process, job_kill_timer): Don't hardcode
JOB_STOPPING here, instead move to the next logical state.
(job_kill_process): Notify subscribed processes that we killed
the job.
(job_start, job_stop): Notify subscribed processes of a change of
goal that doesn't result in an immediate state change.
* init/event.c (event_trigger_edge, event_trigger_level): Swap
order so that events are announced before processed.
* init/control.c (control_handle): Handle requests to watch and
unwatch jobs and events.
* init/tests/test_control.c (test_cb_child, test_cb): Check that
subscriptions work.
* init/tests/test_control.c (test_cb_child): Add a sleep to avoid
a race that upsets gdb, have tried this with a STOP/CONT interlock
but can't seem to find where the child should reach first.
* init/job.c (job_change_state): Notify the control handler.
* init/event.c (event_trigger_edge, event_trigger_level): Pass
event to the control handler.
* init/tests/test_control.c (test_cb_child): Expect to receive
job status events as well.
* init/Makefile.am (test_event_LDADD, test_process_LDADD)
(test_job_LDADD): Add control.o to the linkage.
* init/control.c (control_cb): Don't display an error for
ECONNREFUSED, just remove any subscriptions.
* init/tests/test_control.c (test_handle_job, test_handle_error):
Clean up our subscriptions properly.
* init/control.c (control_handle_job): Function to send out an
UPSTART_JOB_STATUS message to subscribed processes whenever a
job state changes.
(control_handle_event): Function to send out an
UPSTART_EVENT_TRIGGERED message to subscribed processes whenever
an event is triggered.
* init/control.h: Update.
* init/tests/test_control.c (test_handle_job, test_handle_event):
Check that the functions work properly.
* init/control.c (control_handle): Handle messages that trigger
edge and level events; subscribe the process to receive notification
of job changes during the event.
* init/tests/test_control.c (test_cb_child): Check that the messages
are handled properly (without subscription check).
* init/control.c (control_cb): Unsubscribe a process if it stops
listening.
* init/control.c (control_send): Copy the pointers in the new
event messages.
* init/tests/test_control.c (test_send): Check the pointers are
copied across correctly.
* init/control.c (control_subscribe): Add function to handle
processes that want to subscribe to changes.
(control_init): Initialise the subscriptions list.
* init/control.h: Add structures and prototypes.
* init/tests/test_control.c (test_subscribe): Test the function.
* upstart/control.h (UpstartMsgType): add messages for triggering
edge and level events, receiving the trigger for an event and for
watching jobs and events.
(UpstartEventTriggerEdgeMsg, UpstartEventTriggerLevelMsg)
(UpstartEventTriggeredMsg, UpstartWatchJobsMsg)
(UpstartUnwatchJobsMsg, UpstartWatchEventsMsg):
(UpstartUnwatchEventsMsg): Add structures for the new messages.
(UpstartMsg): And add them to the union.
* upstart/control.c (WireEventPayload): The event messages can all
share a wire payload type; the watch messages don't need any special
payload.
(upstart_send_msg_to): Add the payloads onto the wire.
(upstart_recv_msg): And take the payloads back off the wire.
* upstart/tests/test_control.c (test_messages): Test the new
message types.
* upstart/control.h (UpstartJobStatusMsg): add a process id.
* upstart/control.c (WireJobStatusPayload): and here too.
(upstart_send_msg_to): copy the process id onto the wire.
(upstart_recv_msg): copy the process id from the wire.
* init/control.c (control_handle): Fill in the pid from the job.
* upstart/tests/test_control.c (test_messages): Check the pid gets
passed across the wire properly.
* init/control.c (control_cb): Disable the poll for write once the
send queue becomes empty.
* upstart/Makefile.am (libupstart_la_SOURCES): Correct ordering.
* init/control.c (control_handle): Add missing break.
* upstart/job.c (job_goal_name, process_state_name): For completeness
add these two functions as well.
* upstart/job.h: Update.
* upstart/tests/test_job.c (test_goal_name)
(test_process_state_name): Test the new functions.
* init/job.c (job_state_name): Move this utility function from here
* upstart/job.c (job_state_name): to here so all clients can use
it.
* init/job.h: Update.
* upstart/job.h: Update.
* init/tests/test_job.c (test_state_name): Move the test case from here
* upstart/tests/test_job.c: to here as well.
* upstart/Makefile.am (libupstart_la_SOURCES): Build and link job.c
(TESTS): Run the job test cases
(test_job_SOURCES, test_job_LDFLAGS, test_job_LDADD): Details for
job test case binary.
* init/Makefile.am (test_job_LDADD, test_process_LDADD)
(test_event_LDADD): Link to libupstart.la
* init/control.c: Code to handle the server end of the control
socket, a bit more complex than a client as we want to avoid
blocking on malcious clients.
* init/control.h: Prototypes.
* init/tests/test_control.c: Test the control code.
* init/Makefile.am (init_SOURCES): Build and link control.c
using the control.h header
(init_LDADD): Link to libupstart as well
(TESTS): Build and run the control test suite.
(test_control_SOURCES, test_control_LDFLAGS, test_control_LDADD):
Details for control test suite binary.
* upstart/control.c: Add a way to disable the safety checks.
* upstart/tests/test_control.c (test_free): Fix bad test case.
* upstart/control.c (upstart_recv_msg): fixed bogus return type
for recvmsg from size_t to ssize_t so we don't infiniloop on error.
* upstart/control.c (upstart_send_msg_to, upstart_recv_msg): Avoid
job_start as the short-cut for assigning name, as that might become
a more complex message eventually. Use job_query instead.
* upstart/control.c (upstart_free): Add wrapper function around
nih_free so we're a proper library and don't expose libnih too much
(upstart_recv_msg): Stash the sender pid in an argument.
* upstart/control.h: Update.
* upstart/tests/test_control.c (test_recv_msg): Test pid is
returned properly.
(test_free): Test the nih_free wrapper.
* init/job.c (job_run_script): Document future FIXME.
* init/exent.h, init/job.h, init/process.h: Fix up headers.
* upstart/control.c, upstart/control.h, upstart/errors.h,
upstart/job.h, upstart/libupstart.h: Fix up headers.
* upstart/control.c: Write the code to handle the control socket
and communication over it; turns out this was possible to write so
that both ends are handled in the same code.
* upstart/control.h: Structures and prototypes.
* upstart/tests/test_control.c: Test the new code.
* upstart/Makefile.am (libupstart_la_LIBADD): Link to libnih
* upstart/errors.h: Header file containing errors raised by
libupstart.
* upstart/libupstart.h: Include errors.h
2006-08-15 Scott James Remnant <scott@netsplit.com>
* init/event.h: Add missing attribute for event_new()
* init/job.h (JobGoal, JobState, ProcessState, ConsoleType): Move
the enums from here
* upstart/job.h: into here so that we can use them across the
control socket.
* Makefile.am (SUBDIRS): Build the libupstart library
* configure.ac (AC_CONFIG_FILES): Generate upstart/Makefile
* upstart/Makefile.am: Makefile for sub-directory
* upstart/libupstart.ver: Linker version script.
* upstart/libupstart.h: "Include everything" header file.
* TODO: Update.
* init/job.c (job_handle_child): Warn when processes are killed
or exit with an abnormal status. Warn when respawning.
* init/job.c (job_handle_child): Respawn processes that were not
supposed to have died.
* init/tests/test_job.c (test_handle_child): Test the respawn code.
* TODO: Update.
* init/event.c (event_trigger_edge, event_trigger_level): Call
job_handle_event so that we actually do something useful.
* init/Makefile.am (test_event_LDADD): Link to process.o and job.o
now that event.c calls code from job.
* init/job.c (job_start_event): Function to start a job if an event
matches.
(job_stop_event): Function to stop a job if an event matches.
(job_handle_event): Iterate the job list and dispatch the given event,
causing jobs to be stopped or started using the above two functions.
* init/job.h: Update.
* init/tests/test_job.c: Test the new functions.
* init/job.c (job_new): Initialise start_events and stop_events to
an empty list.
* init/job.h (Job): Add start_events and stop_events list heads.
* init/tests/test_job.c (test_new): Check the lists are initialised
correctly to the empty list.
* init/event.c (event_match): Function to check events for equality.
* init/event.h: Update.
* init/tests/test_event.c (test_match): Test function.
* init/job.c (job_change_state): Trigger the level event with the
same name as the job, with the value taken from the state.
* init/tests/test_job.c (test_change_state): Check the event
gets set to the right values as we go.
* init/Makefile.am (test_job_LDADD, test_process_LDADD): Link to
event.o now that job.c uses code from there.
* init/event.c (event_change_value): Rename event_set_value to this
as we intended in the first place; makes it more consistent with job.
Always change the value.
(event_trigger_edge): Add a high-level function to trigger an edge
event.
(event_trigger_level): And another to trigger a level event with
a given value, this inherits the "don't change it" functionality
that was in event_set_value.
* init/event.h: Update.
* init/tests/test_event.c: Test new behaviours and functions.
* init/event.c: Add simple code to keep track of events, whether
they have been recorded or not and their current value if any.
* init/event.h: Structures and prototypes.
* init/tests/test_event.c: Test cases for event code.
* init/Makefile.am (init_SOURCES): Build and link event.c using event.h
(TESTS): Run the event test suite.
(test_event_SOURCES, test_event_LDFLAGS, test_event_LDADD): Details
for event test suite binary.
* init/job.c (job_run_process, job_kill_process, job_kill_timer):
Downgrade error messages to warning as they're not fatal.
(job_change_state): Change info message to be more regular.
* init/job.c (job_start): A very simple, but very necessary, function.
Set the goal of the given job to JOB_START and kick it off.
(job_stop): And its companion, cause a running job to be stopped.
* init/job.h: Update.
* init/tests/test_job.c: Test the functions.
* init/job.c (job_handle_child): Child handler to kick jobs into
the next state when their process dies.
* init/job.h: Update.
* init/tests/test_job.c (test_handle_child): Test the handler
directly by just invoking it with various job states.
2006-08-14 Scott James Remnant <scott@netsplit.com>
* init/tests/test_process.c (test_kill): Use select rather than
poll for consistency with other test cases.
* init/job.c (job_kill_process): Add function to send the active
process of a job the TERM signal, and then set a timer to follow
up with the KILL signal if the job doesn't get cleaned up in time.
(job_kill_timer): Timer callback to send the KILL signal; this
does the same job as the child handler and puts the job into the
next state as there's no point waiting around now.
* init/job.h: Update.
* init/tests/test_job.c (test_kill_process): Test both functions
in one test case (as one is just the bottom half of the other).
* init/tests/test_process.c (test_spawn): Use the right thing in
the test case filename and unlink it to make sure.
* init/job.c (job_change_state): Write the principal state gate
function, called once a state has been left to enter the given new
state (which one should determine with job_next_state). Spawns
the necessary processes or moves to the next appropriate state.
* init/job.h: Update.
* init/tests/test_job.c: Test the state changes.
* init/job.c (job_run_process): Internal function to call
process_spawn and update the job structure.
(job_run_command): Simple(ish) wrapper for the above to split
a command by whitespace, or use a shell if it needs more complex
argument processing.
(job_run_script): More complex wrapper that uses a shell to execute
verbatim script, either using -c or a /dev/fd/NN and feeding the
shell down a pipe to it.
* init/job.h: Update.
* init/tests/test_job.c: Test the new functions.
* init/Makefile.am (init_SOURCES, TESTS): Reorder so that process.c,
which is arguably lower level, comes first.
(test_job_LDADD): Link the process code.
(test_process_LDADD): Swap the order.
* TODO: Update.
* init/process.c (process_spawn): Correct typo (progress -> process),
thanks Johan.
2006-08-12 Scott James Remnant <scott@netsplit.com>
* init/process.c (process_spawn): Correct formatting of function.
* init/process.h (SHELL): Define the location of the shell, all in
the spirit of not hard-coding stuff like this.
* init/job.c (job_new): Initialise all structure members to zero
as this doesn't happen automatically.
2006-08-10 Scott James Remnant <scott@netsplit.com>
* init/job.h (job_state_name): Declare as a const function.
2006-08-09 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_next_state): State transition logic; this uses
our departure from the specification (the goal) so that the state
can always be currently accurate rather than suggestive.
(job_state_name): Cute function to convert enum into a name.
* init/job.h: Update.
* init/tests/test_job.c (test_next_state): Test the transitions.
(test_state_name): And the return values.
* TODO: Add file to keep track of things.
* init/job.c: Include nih/macros.h and nih/list.h
* init/process.c: Include order fixing, include nih/macros.h
* init/tests/test_job.c: Include nih/macros.h and nih/list.h
* init/tests/test_process.c: Include nih/list.h
* init/job.c: Include order fixing.
(job_find_by_name): Function to find a job by its (unique) name.
(job_find_by_pid): Function to find a job by the pid of its process.
* init/job.h: Update.
* init/tests/test_job.c (test_find_by_name, test_find_by_pid): Test
new functions.
* init/process.c (process_spawn): Spawn a process using the job
details to set up the environment, etc.
(process_setup_console): Set up the console according to the job.
(process_setup_limits): Set up the limits according to the job.
(process_setup_environment): Set up the environment according to
the job.
(process_kill): Simple function to send a kill signal or raise an
error; mostly just a wrapper without any particular logic.
* init/process.h: Prototypes and macros.
* init/tests/test_process.c: Test cases.
* init/Makefile.am (init_SOURCES): Build and link process.c and
its header file.
(TESTS): Run the process test suite.
(test_process_SOURCES, test_process_LDFLAGS, test_process_LDADD):
Details for process test sutie binary.
2006-08-08 Scott James Remnant <scott@netsplit.com>
* init/job.c (job_new): nih_list_free is necessary.
* init/tests/test_job.c (test_new): Free job when done.
* init/job.h: Header file to contain the definition of the Job
structure and associated typedefs, etc.
(JobGoal): In a divergence from the specification, we introduced a
"goal" for a job which tells us which way round the state machine
we're going (towards start, or towards stop).
(JobState): Which means this always holds the current state, even
if we're trying to get out of this state (ie. if we've sent the TERM
signal to the running process, we're still in the running state until
it's actually been reaped).
(ProcessState): And in another divergence, we keep the state of the
process so we know whether we need to force a state transition or
can just expect one because something transient is happening.
* init/job.c (job_new): Function to allocate a Job structure, set
the pointers to NULL and other important members to sensible
defaults.
(job_init): Initialise the list of jobs.
* init/tests/test_job.c: Test suite.
* init/Makefile.am (init_SOURCES): Compile and link job.c using
its header file.
(TESTS): Run the job test suite.
(test_job_SOURCES, test_job_LDFLAGS, test_job_LDADD): Details for the
job test suite binary.
2006-08-02 Scott James Remnant <scott@netsplit.com>
* configure.ac: Check for C99
* HACKING: Document dependency on libnih.
2006-07-27 Scott James Remnant <scott@netsplit.com>
* init/Makefile.am (DEFS): Append to the default DEFS list, rather
than overriding, otherwise we lose HAVE_CONFIG_H
2006-07-13 Scott James Remnant <scott@netsplit.com>
* HACKING: Correct incorrect Bazaar URL.
* AUTHORS: Change e-mail address to ubuntu.com.
* HACKING: Update Bazaar and Release URLS.
* configure.ac (AC_COPYRIGHT): Change copyright to Canonical Ltd.
(AC_INIT): Change bug submission address to Launchpad.
* init/main.c: Update header to use Canonical copyright and
credit me as author.
2006-05-16 Scott James Remnant <scott@netsplit.com>
* init/main.c: Add the simplest template main.c
* init/Makefile.am: Add template Makefile.am that builds init from
main.c and links to libnih statically
* configure.ac (AC_CONFIG_FILES): Configure nih and init subdirs.
* Makefile.am (SUBDIRS): Recurse into nih and init subdirs.
2006-05-14 Scott James Remnant <scott@netsplit.com>
* ChangeLog: Initial project infrastructure created.