The PID create and delete functions were written as intended specifically for the main controller program.
PID files are to be used by services and utilities, therefore the PID create and delete functions should also be used there.
Detect if the main PID file is created and then only attempt to delete it on exit (and then do not do so for child processes).
f_signal_close(&data->signal);
- controller_file_pid_delete(*data, setting.path_pid);
+ if (status != F_child && setting.pid_created) {
+ f_status_t status_delete = controller_file_pid_delete(data->pid, setting.path_pid);
+
+ if (F_status_is_error(status_delete) && data->warning.verbosity == f_console_verbosity_debug) {
+ if (F_status_set_fine(status_delete) == F_number_not) {
+ controller_error_pid_bad_match_print(data->warning, setting.path_pid.string, 0);
+ }
+ else {
+ fll_error_file_print(data->warning, F_status_set_fine(status_delete), "controller_file_pid_delete", F_true, setting.path_pid.string, "delete", fll_error_file_type_file);
+ }
+ }
+ }
+
controller_setting_delete_simple(&setting);
controller_delete_data(data);
}
#endif // _di_controller_error_file_print_
+#ifndef _di_controller_error_pid_bad_match_print_
+ void controller_error_pid_bad_match_print(const fll_error_print_t print, const f_string_t path, controller_thread_t *thread) {
+
+ if (thread) f_thread_mutex_lock(&thread->lock.print);
+
+ fprintf(print.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(print.to.stream, "%s%sThe pid file '", print.context.before->string, print.prefix ? print.prefix : f_string_empty_s);
+ fprintf(print.to.stream, "%s%s%s%s", print.context.after->string, print.notable.before->string, path, print.notable.after->string);
+ fprintf(print.to.stream, "%s' doesn't contain the expected number, not deleting file.%s%c", print.context.before->string, print.context.after->string, f_string_eol_s[0]);
+
+ if (thread) controller_print_unlock_flush(print.to.stream, &thread->lock.print);
+ }
+#endif // _di_controller_error_pid_bad_match_print_
+
#ifndef _di_controller_error_print_
void controller_error_print(const fll_error_print_t print, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) {
typedef struct {
bool interruptable;
+ bool pid_created;
uint8_t ready;
f_number_unsigned_t timeout_kill;
#define controller_setting_t_initialize { \
F_false, \
+ F_false, \
0, \
3, \
3, \
extern void controller_error_file_print(const fll_error_print_t print, const f_status_t status, const f_string_t function, const bool fallback, const f_string_t name, const f_string_t operation, const uint8_t type, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
#endif // _di_controller_error_file_print_
+/**
+ * Print the error, locking the print mutex during the print.
+ *
+ * This does not check verbosity.
+ *
+ * @param print
+ * Designates how printing is to be performed.
+ * @param path
+ * The path to the PID file.
+ * @param thread
+ * (optional) The thread data.
+ * Set to NULL to not use (locking will not be performed).
+ *
+ * @see fll_error_print()
+ */
+#ifndef _di_controller_error_pid_bad_match_print_
+ extern void controller_error_pid_bad_match_print(const fll_error_print_t print, const f_string_t path, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_error_pid_bad_match_print_
/**
* Print the error, locking the print mutex during the print.
#endif // _di_controller_file_load_
#ifndef _di_controller_file_pid_create_
- f_status_t controller_file_pid_create(const controller_data_t data, const f_string_static_t path_pid) {
+ f_status_t controller_file_pid_create(const pid_t pid, const f_string_static_t path) {
f_status_t status = F_none;
// the file exists, do not attempt to overwrite.
- if (f_file_exists(path_pid.string) == F_true) {
+ if (f_file_exists(path.string) == F_true) {
return F_status_set_error(F_file_found);
}
{
f_string_dynamic_t path_directory = f_string_dynamic_t_initialize;
- status = f_file_name_directory(path_pid.string, path_pid.used, &path_directory);
+ status = f_file_name_directory(path.string, path.used, &path_directory);
if (F_status_is_error_not(status)) {
status = f_directory_exists(path_directory.string);
file.flag = f_file_flag_write_only;
- status = f_file_stream_open(path_pid.string, f_file_open_mode_truncate_s, &file);
+ status = f_file_stream_open(path.string, f_file_open_mode_truncate_s, &file);
if (F_status_is_error(status)) return status;
- fprintf(file.stream, "%llu%c", data.pid, f_string_eol_s[0]);
+ fprintf(file.stream, "%llu%c", pid, f_string_eol_s[0]);
f_file_stream_close(F_true, &file);
#endif // _di_controller_file_pid_create_
#ifndef _di_controller_file_pid_delete_
- void controller_file_pid_delete(const controller_data_t data, const f_string_static_t path_pid) {
+ f_status_t controller_file_pid_delete(const pid_t pid, const f_string_static_t path) {
// only delete if the file exists and there is no error while checking.
- if (f_file_exists(path_pid.string) != F_true) {
- return;
+ if (f_file_exists(path.string) != F_true) {
+ return F_none;
}
f_status_t status = F_none;
f_file_t pid_file = f_file_t_initialize;
- status = f_file_stream_open(path_pid.string, f_file_open_mode_read_s, &pid_file);
- if (F_status_is_error(status)) return;
+ status = f_file_stream_open(path.string, f_file_open_mode_read_s, &pid_file);
+ if (F_status_is_error(status)) return status;
f_string_dynamic_t pid_buffer = f_string_dynamic_t_initialize;
status = f_file_stream_read(pid_file, 1, &pid_buffer);
- f_file_stream_close(F_true, &pid_file);
+ if (F_status_is_error_not(status)) {
+ status = f_file_stream_close(F_true, &pid_file);
+ }
if (F_status_is_error_not(status)) {
f_number_unsigned_t number = 0;
status = fl_conversion_string_to_decimal_unsigned(pid_buffer.string, range, &number);
- if (F_status_is_error_not(status) && number == data.pid) {
- status = f_file_remove(path_pid.string);
-
- if (F_status_is_error(status) && data.warning.verbosity == f_console_verbosity_debug) {
- fll_error_file_print(data.warning, F_status_set_fine(status), "f_file_remove", F_true, path_pid.string, "delete", fll_error_file_type_file);
- }
+ if (F_status_is_error_not(status) && number == pid) {
+ status = f_file_remove(path.string);
+ }
+ else {
+ status = F_status_set_error(F_number_not);
}
}
f_macro_string_dynamic_t_delete_simple(pid_buffer);
+
+ return status;
}
#endif // _di_controller_file_pid_delete_
// only create pid file when not in validate mode.
if (main.data->parameters[controller_parameter_validate].result == f_console_result_none) {
- status = controller_file_pid_create(*main.data, main.setting->path_pid);
+ status = controller_file_pid_create(main.data->pid, main.setting->path_pid);
// report pid file error but because this could be an "init" program, consider the pid file as optional and continue on.
if (F_status_is_error(status)) {
status = F_none;
}
+ else {
+ main.setting->pid_created = F_true;
+ }
}
return status;
/**
* Create the pid file, if possible.
*
- * @param data
- * The program data.
- * @param path_pid
+ * @param pid
+ * The PID (process id).
+ * @param path
* The file path to the pid file to create.
*
* @return
* @see f_file_stream_open()
*/
#ifndef _di_controller_file_pid_create_
- f_status_t controller_file_pid_create(const controller_data_t data, const f_string_static_t path_pid) f_gcc_attribute_visibility_internal;
+ f_status_t controller_file_pid_create(const pid_t pid, const f_string_static_t path) f_gcc_attribute_visibility_internal;
#endif // _di_controller_file_pid_create_
/**
*
* This is meant to be called on exit and avoids checking status codes, returning void.
*
- * @param data
- * The program data.
- * @param path_pid
+ * @param pid
+ * The PID (process id).
+ * @param path
* The file path to the pid file to create.
+ *
+ * @return
+ * F_none on success.
+ *
+ * F_number_not (with error bit) if the number from the pid file doesn't match the expected pid.
+ *
+ * Errors (with error bit) from: f_file_stream_close().
+ * Errors (with error bit) from: f_file_stream_open().
+ * Errors (with error bit) from: f_file_stream_read().
*/
#ifndef _di_controller_file_pid_delete_
- void controller_file_pid_delete(const controller_data_t data, const f_string_static_t path_pid) f_gcc_attribute_visibility_internal;
+ f_status_t controller_file_pid_delete(const pid_t pid, const f_string_static_t path) f_gcc_attribute_visibility_internal;
#endif // _di_controller_file_pid_delete_
/**