# HG changeset patch # User Paul Boddie # Date 1680642660 -7200 # Node ID f4bc1512b0907d45bc709e566928d97a38246939 # Parent 9cf77374b29925e4a5c57640be774dbe0853c5fc Attempt to deal with programs terminating before a capability can be issued to monitor them by sending the process monitor capability before actually starting a program. This requires any failure to start a program to be communicated via a notification message. Fixed the lack of initialisation of the pending notifications structure member. diff -r 9cf77374b299 -r f4bc1512b090 libexec/include/exec/process_creating.h --- a/libexec/include/exec/process_creating.h Mon Apr 03 22:10:42 2023 +0200 +++ b/libexec/include/exec/process_creating.h Tue Apr 04 23:11:00 2023 +0200 @@ -76,8 +76,6 @@ long init_external_pager(l4_cap_idx_t *pager); - long init_process_monitor(l4_cap_idx_t *monitor); - long configure_task(); long allocate_internal_pager(); @@ -90,10 +88,14 @@ long start_program(l4_cap_idx_t monitor, int argc, const char *argv[]); + long _start(int argc, const char *argv[], l4_cap_idx_t process); + public: explicit ProcessCreating(const char *rm_filename, file_t *rm_file); - virtual long start(int argc, const char *argv[], l4_cap_idx_t *process); + virtual long init_process_monitor(l4_cap_idx_t *monitor); + + virtual long start(int argc, const char *argv[], l4_cap_idx_t process); }; /* vim: tabstop=2 expandtab shiftwidth=2 diff -r 9cf77374b299 -r f4bc1512b090 libexec/include/exec/process_creator_resource.h --- a/libexec/include/exec/process_creator_resource.h Mon Apr 03 22:10:42 2023 +0200 +++ b/libexec/include/exec/process_creator_resource.h Tue Apr 04 23:11:00 2023 +0200 @@ -47,9 +47,11 @@ void *interface() { return static_cast(this); } - /* Process creator interface methods. */ + /* Local operations. */ - virtual long start(int argc, const char *argv[], l4_cap_idx_t *process); + virtual long init_process(l4_cap_idx_t *process); + + virtual long start(int argc, const char *argv[], l4_cap_idx_t process); /* Opener interface methods. */ diff -r 9cf77374b299 -r f4bc1512b090 libexec/lib/src/process_creating.cc --- a/libexec/lib/src/process_creating.cc Mon Apr 03 22:10:42 2023 +0200 +++ b/libexec/lib/src/process_creating.cc Tue Apr 04 23:11:00 2023 +0200 @@ -86,6 +86,7 @@ long ProcessCreating::init_external_pager(l4_cap_idx_t *pager) { _exec_pager = new ExternalPager(0, 10 * L4_PAGESIZE); + _exec_pager->set_monitor(_monitor); /* Initialise pager regions for the region mapper. */ @@ -119,13 +120,7 @@ /* Start the monitor in a separate thread. */ - long err = ResourceServer(_monitor).start_thread(monitor); - - if (err) - return err; - - _exec_pager->set_monitor(_monitor); - return L4_EOK; + return ResourceServer(_monitor).start_thread(monitor); } /* Configure the environment for the task. */ @@ -369,10 +364,8 @@ program arguments, returning a reference to the process monitor as an object for interacting with the process. */ -long ProcessCreating::start(int argc, const char *argv[], l4_cap_idx_t *process) +long ProcessCreating::_start(int argc, const char *argv[], l4_cap_idx_t process) { - std::lock_guard guard(_lock); - /* Open the program file, handling any error conditions. If successfully opened, it will be closed when the process terminates. */ @@ -405,10 +398,6 @@ if (err) return err; - err = init_process_monitor(process); - if (err) - return err; - err = configure_task(); if (err) return err; @@ -421,7 +410,7 @@ if (err) return err; - err = start_program(*process, argc, argv); + err = start_program(process, argc, argv); if (err) return err; @@ -444,5 +433,21 @@ return L4_EOK; } +/* Start the given program, notifying the process monitor upon any error. */ + +long ProcessCreating::start(int argc, const char *argv[], l4_cap_idx_t process) +{ + std::lock_guard guard(_lock); + + long err = _start(argc, argv, process); + + /* Communicate the error using the signal value. */ + + if (err) + _monitor->notify_all(NOTIFY_TASK_ERROR, (notify_values_t) {0, err}); + + return err; +} + /* vim: tabstop=2 expandtab shiftwidth=2 */ diff -r 9cf77374b299 -r f4bc1512b090 libexec/lib/src/process_creator_context_resource.cc --- a/libexec/lib/src/process_creator_context_resource.cc Mon Apr 03 22:10:42 2023 +0200 +++ b/libexec/lib/src/process_creator_context_resource.cc Tue Apr 04 23:11:00 2023 +0200 @@ -67,9 +67,27 @@ printf("argv[%d] = %s\n", i, argv[i]); } - /* Start the new process, obtaining a reference to it. */ + /* Obtain a reference to a new process and send the reference to the client. + This must be done in advance of actually starting the program since the + program may complete before the client gets the reference. */ + + long err = _creator->init_process(process); + + if (!err) + err = complete_ProcessCreatorContext_start(*process); + + /* Attempt to communicate any error from these activities. */ - return _creator->start(argc, argv, process); + if (err) + return err; + + /* Attempt to actually start the process. Errors cannot be communicated as a + reply, so a notification is sent via the process monitor instead by the + process creator. */ + + _creator->start(argc, argv, *process); + + return IPC_MESSAGE_SENT; } /* vim: tabstop=4 expandtab shiftwidth=4 diff -r 9cf77374b299 -r f4bc1512b090 libexec/lib/src/process_creator_resource.cc --- a/libexec/lib/src/process_creator_resource.cc Mon Apr 03 22:10:42 2023 +0200 +++ b/libexec/lib/src/process_creator_resource.cc Tue Apr 04 23:11:00 2023 +0200 @@ -48,9 +48,14 @@ /* ProcessCreator interface methods. */ +long ProcessCreatorResource::init_process(l4_cap_idx_t *process) +{ + return _creating.init_process_monitor(process); +} + /* Start the new process, obtaining a reference to it. */ -long ProcessCreatorResource::start(int argc, const char *argv[], l4_cap_idx_t *process) +long ProcessCreatorResource::start(int argc, const char *argv[], l4_cap_idx_t process) { return _creating.start(argc, argv, process); } diff -r 9cf77374b299 -r f4bc1512b090 libfsclient/include/fsclient/process.h --- a/libfsclient/include/fsclient/process.h Mon Apr 03 22:10:42 2023 +0200 +++ b/libfsclient/include/fsclient/process.h Tue Apr 04 23:11:00 2023 +0200 @@ -58,8 +58,9 @@ process_t *process_new(); void process_close(process_t *process); +long process_error(process_t *process); void process_init(process_t *process); -long process_start(process_t *process, int argc, char *argv[]); +long process_start(process_t *process, int argc, const char *argv[]); /* Notification support. */ diff -r 9cf77374b299 -r f4bc1512b090 libfsclient/lib/src/file.cc --- a/libfsclient/lib/src/file.cc Mon Apr 03 22:10:42 2023 +0200 +++ b/libfsclient/lib/src/file.cc Tue Apr 04 23:11:00 2023 +0200 @@ -95,6 +95,7 @@ /* Initialise the notifiable section of the structure. */ file->notifiable.notifications = 0; + file->notifiable.pending_notifications = 0; file->notifiable.base = (notifiable_base_t *) file; file->notifiable.handler = NULL; } diff -r 9cf77374b299 -r f4bc1512b090 libfsclient/lib/src/process.cc --- a/libfsclient/lib/src/process.cc Mon Apr 03 22:10:42 2023 +0200 +++ b/libfsclient/lib/src/process.cc Tue Apr 04 23:11:00 2023 +0200 @@ -34,6 +34,17 @@ +/* Utility functions. */ + +static bool _process_terminated(process_t *process) +{ + return ((process->notifiable.notifications & NOTIFY_TASK_SIGNAL) && + (process->notifiable.values.sig == 0)) || + (process->notifiable.notifications & NOTIFY_TASK_ERROR); +} + + + /* Create a new process object. */ process_t *process_new() @@ -60,6 +71,16 @@ process_init(process); } +/* Return any process initiation error. */ + +long process_error(process_t *process) +{ + if (process->notifiable.notifications & NOTIFY_TASK_ALL) + return process->notifiable.values.val; + else + return L4_EOK; +} + /* Initialise the given process structure. */ void process_init(process_t *process) @@ -69,6 +90,7 @@ /* Initialise the notifiable section of the structure. */ process->notifiable.notifications = 0; + process->notifiable.pending_notifications = 0; process->notifiable.base = (notifiable_base_t *) process; process->notifiable.handler = NULL; } @@ -76,7 +98,7 @@ /* Start a process using the given arguments. NOTE: This does not yet obtain input/output pipes. */ -long process_start(process_t *process, int argc, char *argv[]) +long process_start(process_t *process, int argc, const char *argv[]) { l4_cap_idx_t server = l4re_env_get_cap(ENV_PROCESS_SERVER_NAME); @@ -112,6 +134,7 @@ /* Initialise the notifiable section of the structure. */ process->notifiable.notifications = 0; + process->notifiable.pending_notifications = 0; process->notifiable.base = (notifiable_base_t *) process; /* Close the context, although a separate mechanism could permit contexts to @@ -204,12 +227,8 @@ /* Unsubscribe if a termination notification has been received. */ - if (!err && (process->notifiable.notifications & NOTIFY_TASK_SIGNAL) && - (process->notifiable.values.sig == 0)) - { + if (!err && _process_terminated(process)) process_notify_unsubscribe(process, notifier); - process_close(process); - } return err; } @@ -225,12 +244,8 @@ /* Unsubscribe if a termination notification has been received. */ - if (!err && ((*process)->notifiable.notifications & NOTIFY_TASK_SIGNAL) && - ((*process)->notifiable.values.sig == 0)) - { + if (!err && _process_terminated(*process)) process_notify_unsubscribe(*process, notifier); - process_close(*process); - } return err; } diff -r 9cf77374b299 -r f4bc1512b090 libsystypes/include/systypes/base.h --- a/libsystypes/include/systypes/base.h Mon Apr 03 22:10:42 2023 +0200 +++ b/libsystypes/include/systypes/base.h Tue Apr 04 23:11:00 2023 +0200 @@ -49,7 +49,8 @@ typedef struct { - unsigned long sig, val; /* signal-specific values */ + unsigned long sig; /* signal number */ + long val; /* signal-specific value */ } notify_values_t; @@ -62,6 +63,11 @@ NOTIFY_PEER_CLOSED = 0x004, /* closing files and pipes */ NOTIFY_FILE_OPENED = 0x008, /* opening files in directories */ NOTIFY_TASK_SIGNAL = 0x100, /* signal from task */ + NOTIFY_TASK_ERROR = 0x200, /* error when creating task */ + + /* Combinations of flags. */ + + NOTIFY_TASK_ALL = 0x300, }; /* Notifiable object types. */ diff -r 9cf77374b299 -r f4bc1512b090 tests/dstest_exec.cc --- a/tests/dstest_exec.cc Mon Apr 03 22:10:42 2023 +0200 +++ b/tests/dstest_exec.cc Tue Apr 04 23:11:00 2023 +0200 @@ -28,6 +28,62 @@ +static long test_process(int argc, const char *argv[]) +{ + /* Obtain the common notifier. */ + + process_notifier_t *notifier = process_notify_task(); + + /* Create a new process structure. */ + + process_t process; + + process_init(&process); + + /* Start the process. */ + + long err = process_start(&process, argc, argv); + + if (err) + { + printf("Could not start process: %s\n", l4sys_errtostr(err)); + return err; + } + + printf("Finished program initiation.\n"); + + /* Subscribe to the process for notifications. */ + + err = process_notify_subscribe(&process, NOTIFY_TASK_ALL, notifier); + + if (err) + { + printf("Could not subscribe to process: %s\n", l4sys_errtostr(err)); + return err; + } + + /* Wait for a signal from the process. */ + + err = process_notify_wait_process(&process, notifier); + + if (err) + { + printf("Could not wait for process: %s\n", l4sys_errtostr(err)); + return err; + } + + notify_flags_t flags = process_notifications(&process); + notify_values_t values = process_notification_values(&process); + + printf("End process (flags %" pFMTnotify_flags "x values: %ld, %ld)\n", flags, values.sig, values.val); + + err = process_error(&process); + process_close(&process); + return err; +} + + + int main(int argc, char *argv[]) { long err; @@ -42,52 +98,30 @@ process_notifier_t *notifier = process_notify_task(); - /* Create a new process structure. */ - - process_t process; + /* Start a process for a non-existent program. */ - process_init(&process); + printf("Start non-existent program...\n"); - printf("Start process...\n"); + const char *bad_argv[] = {"non_existent_program"}; - /* Start a process for the given program. */ - - err = process_start(&process, argc - 1, argv + 1); + err = test_process(1, bad_argv); - if (err) + if (!err) { - printf("Could not start process: %s\n", l4sys_errtostr(err)); + printf("Non-existent program was apparently successfully started.\n"); return 1; } - printf("Finished program initiation.\n"); + printf("Non-existent program result: %s\n", l4sys_errtostr(err)); + + /* Start a process for the given program. */ - /* Subscribe to the process for notifications. */ + printf("Start process...\n"); - err = process_notify_subscribe(&process, NOTIFY_TASK_SIGNAL, notifier); + err = test_process(argc - 1, (const char **) argv + 1); if (err) - { - printf("Could not subscribe to process: %s\n", l4sys_errtostr(err)); return 1; - } - - /* Wait for a signal from the process. */ - - err = process_notify_wait_process(&process, notifier); - - if (err) - { - printf("Could not wait for process: %s\n", l4sys_errtostr(err)); - return 1; - } - - notify_flags_t flags = process_notifications(&process); - notify_values_t values = process_notification_values(&process); - - process_close(&process); - - printf("End process (flags %" pFMTnotify_flags "x values: %ld, %ld)\n", flags, values.sig, values.val); process_notify_close(notifier); diff -r 9cf77374b299 -r f4bc1512b090 tests/dstest_exec_many.cc --- a/tests/dstest_exec_many.cc Mon Apr 03 22:10:42 2023 +0200 +++ b/tests/dstest_exec_many.cc Tue Apr 04 23:11:00 2023 +0200 @@ -57,7 +57,7 @@ /* Start a process for the given program. */ - err = process_start(&process, argc - 2, argv + 2); + err = process_start(&process, argc - 2, (const char **) argv + 2); if (err) { @@ -69,7 +69,7 @@ /* Subscribe to the process for notifications. */ - err = process_notify_subscribe(&process, NOTIFY_TASK_SIGNAL, notifier); + err = process_notify_subscribe(&process, NOTIFY_TASK_ALL, notifier); if (err) { @@ -90,9 +90,9 @@ notify_flags_t flags = process_notifications(&process); notify_values_t values = process_notification_values(&process); - process_close(&process); + printf("[%d/%d] End process (flags %" pFMTnotify_flags "x values: %ld, %ld)\n", i, num_processes, flags, values.sig, values.val); - printf("[%d/%d] End process (flags %" pFMTnotify_flags "x values: %ld, %ld)\n", i, num_processes, flags, values.sig, values.val); + process_close(&process); } process_notify_close(notifier);