From eb030759d2c725fb86329f61abdc064f076d153b Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Mon, 15 Nov 2021 13:12:03 -1000 Subject: [PATCH 1/4] Improve how movie and batch seek to cleanup on premature exits See #6007 for motivation. This PR moves the creation of the cleanup script up front and once we pass the section where the working dir has been created we no longer Return on error but jump to the end of the program so that we can run the cleanup_script before exiting with the error. --- src/batch.c | 114 +++++++++++++++++++++------------------ src/movie.c | 151 ++++++++++++++++++++++++++++------------------------ 2 files changed, 141 insertions(+), 124 deletions(-) diff --git a/src/batch.c b/src/batch.c index 37447da9ef7..d25495ac77c 100644 --- a/src/batch.c +++ b/src/batch.c @@ -414,7 +414,7 @@ static int parse (struct GMT_CTRL *GMT, struct BATCH_CTRL *Ctrl, struct GMT_OPTI #define Return(code) {Free_Ctrl (GMT, Ctrl); gmt_end_module (GMT, GMT_cpy); bailout (code);} EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { - int error = 0, precision; + int error = GMT_NOERROR, current_error, precision; int (*run_script)(const char *); /* pointer to system function or a dummy */ unsigned int n_values = 0, n_jobs = 0, job, i_job, col, k, n_cores_unused, n_to_run; @@ -537,6 +537,41 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { Return (GMT_RUNTIME_ERROR); } + /* Prepare the cleanup script */ + sprintf (cleanup_file, "batch_cleanup.%s", extension[Ctrl->In.mode]); + GMT_Report (API, GMT_MSG_INFORMATION, "Create cleanup script %s\n", cleanup_file); + if ((fp = fopen (cleanup_file, "w")) == NULL) { + GMT_Report (API, GMT_MSG_ERROR, "Unable to create cleanup file %s - exiting\n", cleanup_file); + Return (GMT_ERROR_ON_FOPEN); + } + gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ + if (Ctrl->W.active) { /* Want to delete the entire work directory */ + gmt_set_comment (fp, Ctrl->In.mode, "Cleanup script removes working directory with job files"); + /* Delete the entire working directory with batch jobs and tmp files */ + fprintf (fp, "%s %s\n", rmdir[Ctrl->In.mode], tmpwpath); + } + else { /* Just delete the remaining script files */ + /* On Windows to do remove a file in a subdir one need to use back slashes */ + char dir_sep_ = (Ctrl->In.mode == GMT_DOS_MODE) ? '\\' : '/'; + GMT_Report (API, GMT_MSG_INFORMATION, "%u job product sets saved in directory: %s\n", n_jobs, workdir); + if (Ctrl->S[BATCH_PREFLIGHT].active) /* Remove the preflight script */ + fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep_, pre_file); + if (Ctrl->S[BATCH_POSTFLIGHT].active) /* Remove the postflight script */ + fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep_, post_file); + fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep_, init_file); /* Delete the init script */ + fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep_, main_file); /* Delete the main script */ + } + fclose (fp); +#ifndef WIN32 /* Set executable bit if not Windows cmd */ + if (chmod (cleanup_file, S_IRWXU)) { + GMT_Report (API, GMT_MSG_ERROR, "Unable to make cleanup script %s executable - exiting\n", cleanup_file); + Return (GMT_RUNTIME_ERROR); + } +#endif + + /* Here the cleanup_script has been completed and from now on we do not Return but set error code and jump to + * the end of the program at tag clean_then_die: */ + /* We use DATADIR to include the top and working directory so any files we supply or create can be found while inside job directory */ if (GMT->session.DATADIR) /* Prepend initial and subdir as new datadirs to the existing search list */ @@ -560,7 +595,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if ((fp = fopen (init_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create file %s - exiting\n", init_file); batch_close_files (Ctrl); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } sprintf (string, "Static parameters set for processing sequence %s", Ctrl->N.prefix); @@ -589,12 +624,13 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { GMT_Report (API, GMT_MSG_ERROR, "Your preflight file %s is not in GMT modern node - exiting\n", pre_file); fclose (Ctrl->In.fp); Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } GMT_Report (API, GMT_MSG_INFORMATION, "Create preflight script %s and execute it\n", pre_file); if ((fp = fopen (pre_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create preflight script %s - exiting\n", pre_file); fclose (Ctrl->In.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ gmt_set_comment (fp, Ctrl->In.mode, "Preflight script"); @@ -622,7 +658,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if (chmod (pre_file, S_IRWXU)) { GMT_Report (API, GMT_MSG_ERROR, "Unable to make preflight script %s executable - exiting.\n", pre_file); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } #endif /* Run the pre-flight now which may or may not create a needed later via -T, as well as needed data files */ @@ -630,7 +666,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if ((error = system (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running preflight script %s returned error %d - exiting.\n", pre_file, error); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } } @@ -641,12 +677,12 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if ((D = GMT_Read_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_NONE, GMT_READ_NORMAL, NULL, Ctrl->T.file, NULL)) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to read time file: %s - exiting\n", Ctrl->T.file); fclose (Ctrl->In.fp); - Return (API->error); + error = API->error; goto clean_then_die; } if (D->n_segments > 1) { /* We insist on a simple file structure with a single segment */ GMT_Report (API, GMT_MSG_ERROR, "Your time file %s has more than one segment - reformat first\n", Ctrl->T.file); fclose (Ctrl->In.fp); - Return (API->error); + error = API->error; goto clean_then_die; } n_jobs = (unsigned int)D->n_records; /* Number of records means number of jobs */ n_values = (unsigned int)D->n_columns; /* The number of per-job parameters we need to place into the per-job parameter files */ @@ -656,7 +692,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { char output[GMT_VF_LEN] = {""}, cmd[GMT_LEN128] = {""}; unsigned int V = GMT->current.setting.verbose; if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_NONE, GMT_OUT|GMT_IS_REFERENCE, NULL, output) == GMT_NOTSET) { - Return (API->error); + error = API->error; goto clean_then_die; } if (GMT->common.f.active[GMT_IN]) sprintf (cmd, "-T%s -o1 -f%s --GMT_HISTORY=readonly T = %s", Ctrl->T.file, GMT->common.f.string, output); @@ -665,11 +701,11 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { GMT_Report (API, GMT_MSG_INFORMATION, "Calling gmtmath with args %s\n", cmd); GMT->current.setting.verbose = GMT_MSG_ERROR; /* So we don't get unwanted verbosity from gmtmath */ if (GMT_Call_Module (API, "gmtmath", GMT_MODULE_CMD, cmd)) { - Return (API->error); /* Some sort of failure */ + error = API->error; goto clean_then_die; } GMT->current.setting.verbose = V; /* Restore */ if ((D = GMT_Read_VirtualFile (API, output)) == NULL) { /* Load in the data array */ - Return (API->error); /* Some sort of failure */ + error = API->error; goto clean_then_die; } n_jobs = (unsigned int)D->n_records; /* Number of records means number of jobs */ n_values = (unsigned int)D->n_columns; /* The number of per-job parameters we need to place into the per-job parameter files */ @@ -685,7 +721,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if (n_jobs == 0) { /* So not good... */ GMT_Report (API, GMT_MSG_ERROR, "No jobs specified! - exiting.\n"); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } if (!n_written) { /* Rewrite the init file to place the BATCH_NJOBS there */ @@ -694,7 +730,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if ((fp = fopen (init_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create file %s - exiting\n", init_file); batch_close_files (Ctrl); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } sprintf (string, "Static parameters set for processing sequence %s", Ctrl->N.prefix); @@ -729,7 +765,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if ((fp = fopen (post_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create postflight file %s - exiting\n", post_file); fclose (Ctrl->In.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ gmt_set_comment (fp, Ctrl->In.mode, "Postflight script"); @@ -758,7 +794,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if (chmod (post_file, S_IRWXU)) { GMT_Report (API, GMT_MSG_ERROR, "Unable to make postflight script %s executable - exiting\n", post_file); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } #endif } @@ -775,7 +811,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if ((fp = fopen (param_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create job parameter file %s - exiting\n", param_file); fclose (Ctrl->In.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } sprintf (state_prefix, "Parameter file for job %s", state_tag); gmt_set_comment (fp, Ctrl->In.mode, state_prefix); @@ -813,7 +849,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if ((fp = fopen (main_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create loop job script file %s - exiting\n", main_file); fclose (Ctrl->In.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ gmt_set_comment (fp, Ctrl->In.mode, "Main job loop script"); @@ -858,39 +894,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { #ifndef WIN32 /* Set executable bit if not Windows cmd */ if (chmod (main_file, S_IRWXU)) { GMT_Report (API, GMT_MSG_ERROR, "Unable to make script %s executable - exiting\n", main_file); - Return (GMT_RUNTIME_ERROR); - } -#endif - - /* Prepare the cleanup script */ - sprintf (cleanup_file, "batch_cleanup.%s", extension[Ctrl->In.mode]); - GMT_Report (API, GMT_MSG_INFORMATION, "Create cleanup script %s\n", cleanup_file); - if ((fp = fopen (cleanup_file, "w")) == NULL) { - GMT_Report (API, GMT_MSG_ERROR, "Unable to create cleanup file %s - exiting\n", cleanup_file); - Return (GMT_ERROR_ON_FOPEN); - } - gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ - if (Ctrl->W.active) { /* Want to delete the entire work directory */ - gmt_set_comment (fp, Ctrl->In.mode, "Cleanup script removes working directory with job files"); - /* Delete the entire working directory with batch jobs and tmp files */ - fprintf (fp, "%s %s\n", rmdir[Ctrl->In.mode], tmpwpath); - } - else { /* Just delete the remaining script files */ - /* On Windows to do remove a file in a subdir one need to use back slashes */ - char dir_sep_ = (Ctrl->In.mode == GMT_DOS_MODE) ? '\\' : '/'; - GMT_Report (API, GMT_MSG_INFORMATION, "%u job product sets saved in directory: %s\n", n_jobs, workdir); - if (Ctrl->S[BATCH_PREFLIGHT].active) /* Remove the preflight script */ - fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep_, pre_file); - if (Ctrl->S[BATCH_POSTFLIGHT].active) /* Remove the postflight script */ - fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep_, post_file); - fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep_, init_file); /* Delete the init script */ - fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep_, main_file); /* Delete the main script */ - } - fclose (fp); -#ifndef WIN32 /* Set executable bit if not Windows cmd */ - if (chmod (cleanup_file, S_IRWXU)) { - GMT_Report (API, GMT_MSG_ERROR, "Unable to make cleanup script %s executable - exiting\n", cleanup_file); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } #endif @@ -906,7 +910,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if ((error = run_script (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running master script %s for argument %s returned error %d - exiting.\n", main_file, state_tag, error); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } Return (GMT_NOERROR); /* We are done */ } @@ -934,7 +938,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { GMT_Report (API, GMT_MSG_DEBUG, "Launch script for job %*.*d\n", precision, precision, job); if ((error = system (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running script %s returned error %d - aborting.\n", cmd, error); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } status[job].started = true; /* We have now launched this job job */ job++; /* Advance to next job for next launch */ @@ -971,10 +975,14 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if ((error = run_script (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running postflight script %s returned error %d - exiting.\n", post_file, error); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } } +clean_then_die: + + current_error = error; /* Since we may jump here because of an issue earlier */ + if (!Ctrl->Q.active) { /* Run cleanup script at the end */ if (Ctrl->In.mode == GMT_DOS_MODE) @@ -1007,5 +1015,5 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { Return (error); } - Return (GMT_NOERROR); + Return (current_error); } diff --git a/src/movie.c b/src/movie.c index 814e729cbaf..17c5db76ee1 100644 --- a/src/movie.c +++ b/src/movie.c @@ -1314,7 +1314,7 @@ GMT_LOCAL bool movie_valid_format (char *format, char code) { #define Return(code) {Free_Ctrl (GMT, Ctrl); gmt_end_module (GMT, GMT_cpy); bailout (code);} EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { - int error = 0, precision, scol, srow; + int error = GMT_NOERROR, current_error, precision, scol, srow; int (*run_script)(const char *); /* pointer to system function or a dummy */ unsigned int n_values = 0, n_frames = 0, n_data_frames, first_fade_out_frame = 0, frame, i_frame, col, p_width, p_height, k, T; @@ -1559,6 +1559,40 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { Return (GMT_RUNTIME_ERROR); } + /* Prepare the cleanup script */ + sprintf (cleanup_file, "movie_cleanup.%s", extension[Ctrl->In.mode]); + if ((fp = fopen (cleanup_file, "w")) == NULL) { + GMT_Report (API, GMT_MSG_ERROR, "Unable to create cleanup file %s - exiting\n", cleanup_file); + Return (GMT_ERROR_ON_FOPEN); + } + gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ + if (Ctrl->Z.active) { /* Want to delete the entire frame directory */ + gmt_set_comment (fp, Ctrl->In.mode, "Cleanup script removes working directory with frame files"); + /* Delete the entire working directory with frame jobs and tmp files */ + fprintf (fp, "%s %s\n", rmdir[Ctrl->In.mode], tmpwpath); + } + else { /* Just delete the remaining scripts and PS files */ + GMT_Report (API, GMT_MSG_INFORMATION, "%u frame PNG files saved in directory: %s\n", n_frames, workdir); + if (Ctrl->S[MOVIE_PREFLIGHT].active) /* Remove the preflight script */ + fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, pre_file); + if (Ctrl->S[MOVIE_POSTFLIGHT].active) /* Remove the postflight script */ + fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, post_file); + fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, init_file); /* Delete the init script */ + fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, main_file); /* Delete the main script */ + if (layers) + fprintf (fp, "%s %s%c*.ps\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep); /* Delete any PostScript layers */ + } + fclose (fp); +#ifndef WIN32 /* Set executable bit if not Windows cmd */ + if (chmod (cleanup_file, S_IRWXU)) { + GMT_Report (API, GMT_MSG_ERROR, "Unable to make cleanup script %s executable - exiting\n", cleanup_file); + Return (GMT_RUNTIME_ERROR); + } +#endif + + /* Here the cleanup_script has been completed and from now on we do not Return but set error code and jump to + * the end of the program at tag clean_then_die: */ + /* We use DATADIR to include the top and working directory so any files we supply or create can be found while inside frame directory */ if (GMT->session.DATADIR) /* Prepend initial and subdir as new datadirs to the existing search list */ @@ -1582,7 +1616,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if ((fp = fopen (init_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create file %s - exiting\n", init_file); movie_close_files (Ctrl); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } sprintf (string, "Static parameters set for animation sequence %s", Ctrl->N.prefix); @@ -1616,13 +1650,13 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (is_classic) { GMT_Report (API, GMT_MSG_ERROR, "Your preflight file %s is not in GMT modern node - exiting\n", pre_file); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } GMT_Report (API, GMT_MSG_INFORMATION, "Create preflight script %s and execute it\n", pre_file); if ((fp = fopen (pre_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create preflight script %s - exiting\n", pre_file); fclose (Ctrl->In.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ gmt_set_comment (fp, Ctrl->In.mode, "Preflight script"); @@ -1656,7 +1690,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (chmod (pre_file, S_IRWXU)) { GMT_Report (API, GMT_MSG_ERROR, "Unable to make preflight script %s executable - exiting.\n", pre_file); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } #endif /* Run the pre-flight now which may or may not create a needed later via -T, as well as a background plot */ @@ -1664,7 +1698,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if ((error = system (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running preflight script %s returned error %d - exiting.\n", pre_file, error); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } } place_background = (!access ("movie_background.ps", R_OK)); /* Need to place a background layer in the main frames */ @@ -1677,12 +1711,12 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if ((D = GMT_Read_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_NONE, GMT_READ_NORMAL, NULL, Ctrl->T.file, NULL)) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to read time file: %s - exiting\n", Ctrl->T.file); fclose (Ctrl->In.fp); - Return (API->error); + error = API->error; goto clean_then_die; } if (D->n_segments > 1) { /* We insist on a simple file structure with a single segment */ GMT_Report (API, GMT_MSG_ERROR, "Your time file %s has more than one segment - reformat first\n", Ctrl->T.file); fclose (Ctrl->In.fp); - Return (API->error); + error = API->error; goto clean_then_die; } n_frames = n_data_frames = (unsigned int)D->n_records; /* Number of records means number of frames */ n_values = (unsigned int)D->n_columns; /* The number of per-frame parameters we need to place into the per-frame parameter files */ @@ -1693,7 +1727,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { char output[GMT_VF_LEN] = {""}, cmd[GMT_LEN128] = {""}; unsigned int V = GMT->current.setting.verbose; if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_NONE, GMT_OUT|GMT_IS_REFERENCE, NULL, output) == GMT_NOTSET) { - Return (API->error); + error = API->error; goto clean_then_die; } if (GMT->common.f.active[GMT_IN]) sprintf (cmd, "-T%s -o1 -f%s --GMT_HISTORY=readonly T = %s", Ctrl->T.file, GMT->common.f.string, output); @@ -1702,11 +1736,11 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { GMT_Report (API, GMT_MSG_INFORMATION, "Calling gmtmath with args %s\n", cmd); GMT->current.setting.verbose = GMT_MSG_ERROR; /* So we don't get unwanted verbosity from gmtmath */ if (GMT_Call_Module (API, "gmtmath", GMT_MODULE_CMD, cmd)) { - Return (API->error); /* Some sort of failure */ + error = API->error; goto clean_then_die; } GMT->current.setting.verbose = V; /* Restore */ if ((D = GMT_Read_VirtualFile (API, output)) == NULL) { /* Load in the data array */ - Return (API->error); /* Some sort of failure */ + error = API->error; goto clean_then_die; } n_frames = n_data_frames = (unsigned int)D->n_records; /* Number of records means number of frames */ n_values = (unsigned int)D->n_columns; /* The number of per-frame parameters we need to place into the per-frame parameter files */ @@ -1723,7 +1757,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (n_frames == 0) { /* So not good... */ GMT_Report (API, GMT_MSG_ERROR, "No frames specified! - exiting.\n"); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } if (Ctrl->M.update) /* Now we can determine and update last or middle frame number */ @@ -1733,7 +1767,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (!(Ctrl->K.preserve[GMT_IN] || Ctrl->K.preserve[GMT_OUT]) && n_fade_frames > n_data_frames) { GMT_Report (API, GMT_MSG_ERROR, "Option -K: Combined fading duration cannot exceed animation duration\n"); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } n_fade_frames = 0; /* If clobbering */ if (Ctrl->K.preserve[GMT_IN]) n_fade_frames += Ctrl->K.fade[GMT_IN]; /* We are preserving, not clobbering */ @@ -1746,15 +1780,15 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { I = &Ctrl->item[k][T]; /* Shorthand for this item */ if ((I->mode == MOVIE_LABEL_IS_COL_C || I->mode == MOVIE_LABEL_IS_COL_T) && D == NULL) { /* Need a floating point number */ GMT_Report (API, GMT_MSG_ERROR, "No table given via -T for data-based labels in %c - exiting\n", which[k]); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } if (I->mode == MOVIE_LABEL_IS_COL_C && I->col >= D->n_columns) { GMT_Report (API, GMT_MSG_ERROR, "Data table does not have enough columns for your -%c c%d request - exiting\n", which[k], I->col); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } if (I->mode == MOVIE_LABEL_IS_COL_T && D->table[0]->segment[0]->text == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Data table does not have trailing text for your -%c t%d request - exit\n", which[k], I->col); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } } } @@ -1774,13 +1808,13 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (is_classic) { GMT_Report (API, GMT_MSG_ERROR, "Your postflight file %s is not in GMT modern node - exiting\n", post_file); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } GMT_Report (API, GMT_MSG_INFORMATION, "Create postflight script %s\n", post_file); if ((fp = fopen (post_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create postflight file %s - exiting\n", post_file); fclose (Ctrl->In.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ gmt_set_comment (fp, Ctrl->In.mode, "Postflight script"); @@ -1813,7 +1847,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (chmod (post_file, S_IRWXU)) { GMT_Report (API, GMT_MSG_ERROR, "Unable to make postflight script %s executable - exiting\n", post_file); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } #endif /* Run post-flight now before dealing with the loop so the overlay exists */ @@ -1821,7 +1855,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if ((error = run_script (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running postflight script %s returned error %d - exiting.\n", post_file, error); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } } } @@ -1890,7 +1924,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if ((fp = fopen (param_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create frame parameter file %s - exiting\n", param_file); fclose (Ctrl->In.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } sprintf (state_prefix, "Parameter file for pre-frame %s", state_tag); gmt_set_comment (fp, Ctrl->In.mode, state_prefix); @@ -1911,7 +1945,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if ((fp = fopen (intro_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create movie intro script file %s - exiting\n", intro_file); fclose (Ctrl->E.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } sprintf (extra, "A+M+r,N+f%s", gmt_place_var (Ctrl->In.mode, "MOVIE_FADE")); /* No cropping, image size is fixed, possibly fading */ if (Ctrl->E.fill) {strcat (extra, "+g"); strcat (extra, Ctrl->E.fill);} /* Chose another fade color than black */ @@ -1979,7 +2013,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { #ifndef WIN32 /* Set executable bit if not Windows cmd */ if (chmod (intro_file, S_IRWXU)) { GMT_Report (API, GMT_MSG_ERROR, "Unable to make script %s executable - exiting\n", intro_file); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } #endif } @@ -2006,7 +2040,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if ((fp = fopen (param_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create frame parameter file %s - exiting\n", param_file); fclose (Ctrl->In.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } sprintf (state_prefix, "Parameter file for frame %s", state_tag); gmt_set_comment (fp, Ctrl->In.mode, state_prefix); @@ -2184,7 +2218,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if ((fp = fopen (master_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create loop frame script file %s - exiting\n", master_file); fclose (Ctrl->In.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } if (is_title) { /* Master frame is from the title sequence */ if (Ctrl->M.frame < Ctrl->E.fade[GMT_IN]) /* During title fade-in */ @@ -2326,14 +2360,14 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (chmod (master_file, S_IRWXU)) { GMT_Report (API, GMT_MSG_ERROR, "Unable to make script %s executable - exiting\n", master_file); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } #endif sprintf (cmd, "%s %s %*.*d", sys_cmd_nowait[Ctrl->In.mode], master_file, precision, precision, Ctrl->M.frame); if ((error = run_script (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running script %s returned error %d - exiting.\n", cmd, error); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } GMT_Report (API, GMT_MSG_INFORMATION, "Single master plot (frame %d) built: %s.%s\n", Ctrl->M.frame, Ctrl->N.prefix, Ctrl->M.format); if (!Ctrl->Q.active) { @@ -2341,7 +2375,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (gmt_remove_file (GMT, master_file)) { /* Delete the master_file script */ GMT_Report (API, GMT_MSG_ERROR, "Unable to delete the master file script %s.\n", master_file); fclose (Ctrl->In.fp); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } } if (Ctrl->M.exit) { /* Well, we are done */ @@ -2350,19 +2384,20 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (chdir (topdir)) { /* Should never happen but we do check */ GMT_Report (API, GMT_MSG_ERROR, "Unable to change directory to starting directory - exiting.\n"); perror (topdir); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } if (!Ctrl->Q.active) { /* Delete the entire directory */ - /* Delete the entire working directory with batch jobs and tmp files */ + /* Delete the entire working directory with frame jobs and tmp files */ sprintf (line, "%s %s\n", rmdir[Ctrl->In.mode], tmpwpath); if ((error = system (line))) { GMT_Report (API, GMT_MSG_ERROR, "Deleting the working directory %s returned error %d.\n", workdir, error); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } } if (Ctrl->Z.delete) { /* Delete input scripts */ - if ((error = movie_delete_scripts (GMT, Ctrl))) - Return (error); + if ((error = movie_delete_scripts (GMT, Ctrl))) { + goto clean_then_die; + } } Return (GMT_NOERROR); } @@ -2375,7 +2410,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if ((fp = fopen (main_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create loop frame script file %s - exiting\n", main_file); fclose (Ctrl->In.fp); - Return (GMT_ERROR_ON_FOPEN); + error = GMT_ERROR_ON_FOPEN; goto clean_then_die; } if (Ctrl->K.active) { sprintf (extra, "A+M+r,N+f%s", gmt_place_var (Ctrl->In.mode, "MOVIE_FADE")); /* No cropping, image size is fixed, but fading may be in effect for some frames */ @@ -2453,7 +2488,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { #ifndef WIN32 /* Set executable bit if not Windows cmd */ if (chmod (main_file, S_IRWXU)) { GMT_Report (API, GMT_MSG_ERROR, "Unable to make script %s executable - exiting\n", main_file); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } #endif @@ -2488,7 +2523,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { GMT_Report (API, GMT_MSG_DEBUG, "Launch script for frame %*.*d\n", precision, precision, frame); if ((error = system (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running script %s returned error %d - aborting.\n", cmd, error); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } status[frame].started = true; /* We have now launched this frame job */ frame++; /* Advance to next frame for next launch */ @@ -2523,7 +2558,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (chdir (topdir)) { /* Should never happen but we should check */ GMT_Report (API, GMT_MSG_ERROR, "Unable to change directory to starting directory - exiting.\n"); perror (topdir); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } if (Ctrl->F.active[MOVIE_GIF]) { /* Want an animated GIF */ @@ -2550,7 +2585,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { GMT_Report (API, GMT_MSG_NOTICE, "Running: %s\n", cmd); if ((error = system (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running GIF conversion returned error %d - exiting.\n", error); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } GMT_Report (API, GMT_MSG_INFORMATION, "GIF animation built: %s.gif\n", Ctrl->N.prefix); if (Ctrl->F.skip) GMT_Report (API, GMT_MSG_INFORMATION, "GIF animation reflects every %d frame only\n", Ctrl->F.stride); @@ -2572,7 +2607,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { GMT_Report (API, GMT_MSG_NOTICE, "Running: %s\n", cmd); if ((error = system (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running FFmpeg conversion to MP4 returned error %d - exiting.\n", error); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } GMT_Report (API, GMT_MSG_INFORMATION, "MP4 movie built: %s.mp4\n", Ctrl->N.prefix); } @@ -2595,41 +2630,15 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { GMT_Report (API, GMT_MSG_NOTICE, "Running: %s\n", cmd); if ((error = system (cmd))) { GMT_Report (API, GMT_MSG_ERROR, "Running FFmpeg conversion to webM returned error %d - exiting.\n", error); - Return (GMT_RUNTIME_ERROR); + error = GMT_RUNTIME_ERROR; goto clean_then_die; } GMT_Report (API, GMT_MSG_INFORMATION, "WebM movie built: %s.webm\n", Ctrl->N.prefix); } - /* Prepare the cleanup script */ - sprintf (cleanup_file, "movie_cleanup.%s", extension[Ctrl->In.mode]); - if ((fp = fopen (cleanup_file, "w")) == NULL) { - GMT_Report (API, GMT_MSG_ERROR, "Unable to create cleanup file %s - exiting\n", cleanup_file); - Return (GMT_ERROR_ON_FOPEN); - } - gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ - if (Ctrl->Z.active) { /* Want to delete the entire frame directory */ - gmt_set_comment (fp, Ctrl->In.mode, "Cleanup script removes working directory with frame files"); - /* Delete the entire working directory with batch jobs and tmp files */ - fprintf (fp, "%s %s\n", rmdir[Ctrl->In.mode], tmpwpath); - } - else { /* Just delete the remaining scripts and PS files */ - GMT_Report (API, GMT_MSG_INFORMATION, "%u frame PNG files saved in directory: %s\n", n_frames, workdir); - if (Ctrl->S[MOVIE_PREFLIGHT].active) /* Remove the preflight script */ - fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, pre_file); - if (Ctrl->S[MOVIE_POSTFLIGHT].active) /* Remove the postflight script */ - fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, post_file); - fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, init_file); /* Delete the init script */ - fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, main_file); /* Delete the main script */ - if (layers) - fprintf (fp, "%s %s%c*.ps\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep); /* Delete any PostScript layers */ - } - fclose (fp); -#ifndef WIN32 /* Set executable bit if not Windows cmd */ - if (chmod (cleanup_file, S_IRWXU)) { - GMT_Report (API, GMT_MSG_ERROR, "Unable to make cleanup script %s executable - exiting\n", cleanup_file); - Return (GMT_RUNTIME_ERROR); - } -#endif +clean_then_die: + + current_error = error; /* Since we may jump here because of an issue earlier */ + if (!Ctrl->Q.active) { /* Run cleanup script at the end */ if (Ctrl->In.mode == GMT_DOS_MODE) @@ -2655,5 +2664,5 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { Return (GMT_RUNTIME_ERROR); } - Return (GMT_NOERROR); + Return (current_error); } From 31c895ad500bdac83c8e1f5fe2d361046086a8b8 Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Mon, 15 Nov 2021 16:51:29 -1000 Subject: [PATCH 2/4] Set tmpwpath before making cleanup script --- src/batch.c | 30 +++++++++++++++--------------- src/movie.c | 30 +++++++++++++++--------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/batch.c b/src/batch.c index d25495ac77c..46ac668f63c 100644 --- a/src/batch.c +++ b/src/batch.c @@ -537,6 +537,21 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { Return (GMT_RUNTIME_ERROR); } + /* We use DATADIR to include the top and working directory so any files we supply or create can be found while inside job directory */ + + if (GMT->session.DATADIR) /* Prepend initial and subdir as new datadirs to the existing search list */ + sprintf (datadir, "%s,%s,%s", topdir, cwd, GMT->session.DATADIR); /* Start with topdir */ + else /* Set the initial and prefix subdirectory as data dirs */ + sprintf (datadir, "%s,%s", topdir, cwd); + + gmt_replace_backslash_in_path (datadir); /* Since we will be fprintf-ing the path we must use // for a slash */ + gmt_replace_backslash_in_path (workdir); + + /* Make a path to workdir that works on current architecture (for command line calls) */ + strncpy (tmpwpath, workdir, PATH_MAX); + if (Ctrl->In.mode == GMT_DOS_MODE) /* On Windows to do remove a file in a subdir one need to use back slashes */ + gmt_strrepc (tmpwpath, '/', '\\'); + /* Prepare the cleanup script */ sprintf (cleanup_file, "batch_cleanup.%s", extension[Ctrl->In.mode]); GMT_Report (API, GMT_MSG_INFORMATION, "Create cleanup script %s\n", cleanup_file); @@ -572,21 +587,6 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { /* Here the cleanup_script has been completed and from now on we do not Return but set error code and jump to * the end of the program at tag clean_then_die: */ - /* We use DATADIR to include the top and working directory so any files we supply or create can be found while inside job directory */ - - if (GMT->session.DATADIR) /* Prepend initial and subdir as new datadirs to the existing search list */ - sprintf (datadir, "%s,%s,%s", topdir, cwd, GMT->session.DATADIR); /* Start with topdir */ - else /* Set the initial and prefix subdirectory as data dirs */ - sprintf (datadir, "%s,%s", topdir, cwd); - - gmt_replace_backslash_in_path (datadir); /* Since we will be fprintf-ing the path we must use // for a slash */ - gmt_replace_backslash_in_path (workdir); - - /* Make a path to workdir that works on current architecture (for command line calls) */ - strncpy (tmpwpath, workdir, PATH_MAX); - if (Ctrl->In.mode == GMT_DOS_MODE) /* On Windows to do remove a file in a subdir one need to use back slashes */ - gmt_strrepc (tmpwpath, '/', '\\'); - /* Create the initialization file with settings common to all jobs */ n_written = (n_jobs > 0); /* Know the number of jobs already */ diff --git a/src/movie.c b/src/movie.c index 17c5db76ee1..a56595470db 100644 --- a/src/movie.c +++ b/src/movie.c @@ -1559,6 +1559,21 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { Return (GMT_RUNTIME_ERROR); } + /* We use DATADIR to include the top and working directory so any files we supply or create can be found while inside frame directory */ + + if (GMT->session.DATADIR) /* Prepend initial and subdir as new datadirs to the existing search list */ + sprintf (datadir, "%s,%s,%s", topdir, cwd, GMT->session.DATADIR); /* Start with topdir */ + else /* Set the initial and prefix subdirectory as data dirs */ + sprintf (datadir, "%s,%s", topdir, cwd); + + gmt_replace_backslash_in_path (datadir); /* Since we will be fprintf the path we must use // for a slash */ + gmt_replace_backslash_in_path (workdir); + + /* Make a path to workdir that works on current architecture (for command line calls) */ + strncpy (tmpwpath, workdir, PATH_MAX); + if (Ctrl->In.mode == GMT_DOS_MODE) /* On Windows to do remove a file in a subdir one need to use back slashes */ + gmt_strrepc (tmpwpath, '/', '\\'); + /* Prepare the cleanup script */ sprintf (cleanup_file, "movie_cleanup.%s", extension[Ctrl->In.mode]); if ((fp = fopen (cleanup_file, "w")) == NULL) { @@ -1593,21 +1608,6 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { /* Here the cleanup_script has been completed and from now on we do not Return but set error code and jump to * the end of the program at tag clean_then_die: */ - /* We use DATADIR to include the top and working directory so any files we supply or create can be found while inside frame directory */ - - if (GMT->session.DATADIR) /* Prepend initial and subdir as new datadirs to the existing search list */ - sprintf (datadir, "%s,%s,%s", topdir, cwd, GMT->session.DATADIR); /* Start with topdir */ - else /* Set the initial and prefix subdirectory as data dirs */ - sprintf (datadir, "%s,%s", topdir, cwd); - - gmt_replace_backslash_in_path (datadir); /* Since we will be fprintf the path we must use // for a slash */ - gmt_replace_backslash_in_path (workdir); - - /* Make a path to workdir that works on current architecture (for command line calls) */ - strncpy (tmpwpath, workdir, PATH_MAX); - if (Ctrl->In.mode == GMT_DOS_MODE) /* On Windows to do remove a file in a subdir one need to use back slashes */ - gmt_strrepc (tmpwpath, '/', '\\'); - /* Create the initialization file with settings common to all frames */ n_written = (n_frames > 0); From e6463369fad3963862c09d11e8d11859683faafb Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Mon, 15 Nov 2021 17:08:21 -1000 Subject: [PATCH 3/4] Add zap_workdir command when things go south --- src/batch.c | 16 +++++++++++++--- src/movie.c | 23 ++++++++++++++++------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/batch.c b/src/batch.c index 46ac668f63c..5e823cef465 100644 --- a/src/batch.c +++ b/src/batch.c @@ -432,7 +432,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { char init_file[PATH_MAX] = {""}, state_tag[GMT_LEN16] = {""}, state_prefix[GMT_LEN64] = {""}, param_file[PATH_MAX] = {""}; char pre_file[PATH_MAX] = {""}, post_file[PATH_MAX] = {""}, main_file[PATH_MAX] = {""}, line[PATH_MAX] = {""}, tmpwpath[PATH_MAX] = {""}; char string[GMT_LEN128] = {""}, cmd[GMT_LEN256] = {""}, cleanup_file[PATH_MAX] = {""}, cwd[PATH_MAX] = {""}, conf_file[PATH_MAX]; - char completion_file[PATH_MAX] = {""}, topdir[PATH_MAX] = {""}, workdir[PATH_MAX] = {""}, datadir[PATH_MAX] = {""}; + char completion_file[PATH_MAX] = {""}, topdir[PATH_MAX] = {""}, workdir[PATH_MAX] = {""}, datadir[PATH_MAX] = {""}, zap_workdir[PATH_MAX] = {""}; double percent = 0.0; @@ -552,6 +552,14 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { if (Ctrl->In.mode == GMT_DOS_MODE) /* On Windows to do remove a file in a subdir one need to use back slashes */ gmt_strrepc (tmpwpath, '/', '\\'); + /* Build file names */ + if (Ctrl->S[BATCH_PREFLIGHT].active) + sprintf (pre_file, "batch_preflight.%s", extension[Ctrl->In.mode]); + if (Ctrl->S[BATCH_POSTFLIGHT].active) + sprintf (post_file, "batch_postflight.%s", extension[Ctrl->In.mode]); + sprintf (init_file, "batch_init.%s", extension[Ctrl->In.mode]); + sprintf (main_file, "batch_job.%s", extension[Ctrl->In.mode]); + /* Prepare the cleanup script */ sprintf (cleanup_file, "batch_cleanup.%s", extension[Ctrl->In.mode]); GMT_Report (API, GMT_MSG_INFORMATION, "Create cleanup script %s\n", cleanup_file); @@ -560,6 +568,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { Return (GMT_ERROR_ON_FOPEN); } gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ + sprintf (zap_workdir, "%s %s", rmdir[Ctrl->In.mode], tmpwpath); if (Ctrl->W.active) { /* Want to delete the entire work directory */ gmt_set_comment (fp, Ctrl->In.mode, "Cleanup script removes working directory with job files"); /* Delete the entire working directory with batch jobs and tmp files */ @@ -590,7 +599,6 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { /* Create the initialization file with settings common to all jobs */ n_written = (n_jobs > 0); /* Know the number of jobs already */ - sprintf (init_file, "batch_init.%s", extension[Ctrl->In.mode]); GMT_Report (API, GMT_MSG_INFORMATION, "Create parameter initiation script %s\n", init_file); if ((fp = fopen (init_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create file %s - exiting\n", init_file); @@ -844,7 +852,6 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { /* Now build the main loop script from the mainscript */ - sprintf (main_file, "batch_job.%s", extension[Ctrl->In.mode]); GMT_Report (API, GMT_MSG_INFORMATION, "Create main batch job script %s\n", main_file); if ((fp = fopen (main_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create loop job script file %s - exiting\n", main_file); @@ -1015,5 +1022,8 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { Return (error); } + if (current_error) /* Force removal of work dir since job failed */ + system (zap_workdir); + Return (current_error); } diff --git a/src/movie.c b/src/movie.c index a56595470db..7b35a878680 100644 --- a/src/movie.c +++ b/src/movie.c @@ -1334,7 +1334,8 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { char pre_file[PATH_MAX] = {""}, post_file[PATH_MAX] = {""}, main_file[PATH_MAX] = {""}, line[PATH_MAX] = {""}, version[GMT_LEN32] = {""}; char string[GMT_LEN128] = {""}, extra[GMT_LEN256] = {""}, cmd[GMT_LEN256] = {""}, cleanup_file[PATH_MAX] = {""}, L_txt[GMT_LEN128] = {""}; char png_file[PATH_MAX] = {""}, topdir[PATH_MAX] = {""}, workdir[PATH_MAX] = {""}, datadir[PATH_MAX] = {""}, frame_products[GMT_LEN32] = {""}; - char intro_file[PATH_MAX] = {""}, conf_file[PATH_MAX], tmpwpath[PATH_MAX] = {""}, *script_file = NULL, which[2] = {"LP"}, spacer, dir_sep; + char intro_file[PATH_MAX] = {""}, conf_file[PATH_MAX], tmpwpath[PATH_MAX] = {""}, zap_workdir[PATH_MAX] = {""}, *script_file = NULL, which[2] = {"LP"}; + char spacer, dir_sep; double percent = 0.0, L_col = 0, sx, sy, fade_level = 0.0; @@ -1571,9 +1572,17 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { /* Make a path to workdir that works on current architecture (for command line calls) */ strncpy (tmpwpath, workdir, PATH_MAX); - if (Ctrl->In.mode == GMT_DOS_MODE) /* On Windows to do remove a file in a subdir one need to use back slashes */ + if (Ctrl->In.mode == GMT_DOS_MODE) /* On Windows to remove a file in a subdir one need to use back slashes */ gmt_strrepc (tmpwpath, '/', '\\'); + /* Build file names */ + if (Ctrl->S[MOVIE_PREFLIGHT].active && !Ctrl->S[MOVIE_PREFLIGHT].PS) + sprintf (pre_file, "movie_preflight.%s", extension[Ctrl->In.mode]); + if (Ctrl->S[MOVIE_POSTFLIGHT].active && !Ctrl->S[MOVIE_POSTFLIGHT].PS) + sprintf (post_file, "movie_postflight.%s", extension[Ctrl->In.mode]); + sprintf (init_file, "movie_init.%s", extension[Ctrl->In.mode]); + sprintf (main_file, "movie_frame.%s", extension[Ctrl->In.mode]); + /* Prepare the cleanup script */ sprintf (cleanup_file, "movie_cleanup.%s", extension[Ctrl->In.mode]); if ((fp = fopen (cleanup_file, "w")) == NULL) { @@ -1581,6 +1590,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { Return (GMT_ERROR_ON_FOPEN); } gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ + sprintf (zap_workdir, "%s %s", rmdir[Ctrl->In.mode], tmpwpath); if (Ctrl->Z.active) { /* Want to delete the entire frame directory */ gmt_set_comment (fp, Ctrl->In.mode, "Cleanup script removes working directory with frame files"); /* Delete the entire working directory with frame jobs and tmp files */ @@ -1594,8 +1604,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, post_file); fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, init_file); /* Delete the init script */ fprintf (fp, "%s %s%c%s\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep, main_file); /* Delete the main script */ - if (layers) - fprintf (fp, "%s %s%c*.ps\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep); /* Delete any PostScript layers */ + fprintf (fp, "%s %s%c*.ps\n", rmfile[Ctrl->In.mode], tmpwpath, dir_sep); /* Delete any PostScript layers */ } fclose (fp); #ifndef WIN32 /* Set executable bit if not Windows cmd */ @@ -1611,7 +1620,6 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { /* Create the initialization file with settings common to all frames */ n_written = (n_frames > 0); - sprintf (init_file, "movie_init.%s", extension[Ctrl->In.mode]); GMT_Report (API, GMT_MSG_INFORMATION, "Create parameter initiation script %s\n", init_file); if ((fp = fopen (init_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create file %s - exiting\n", init_file); @@ -1645,7 +1653,6 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { if (Ctrl->S[MOVIE_PREFLIGHT].PS) /* Just got a PS file, nothing to do */ fclose (Ctrl->S[MOVIE_PREFLIGHT].fp); else { /* Run the preflight script */ - sprintf (pre_file, "movie_preflight.%s", extension[Ctrl->In.mode]); is_classic = gmt_script_is_classic (GMT, Ctrl->S[MOVIE_PREFLIGHT].fp); if (is_classic) { GMT_Report (API, GMT_MSG_ERROR, "Your preflight file %s is not in GMT modern node - exiting\n", pre_file); @@ -2405,7 +2412,6 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { /* Now build the main loop script from the mainscript */ - sprintf (main_file, "movie_frame.%s", extension[Ctrl->In.mode]); GMT_Report (API, GMT_MSG_INFORMATION, "Create main movie frame script %s\n", main_file); if ((fp = fopen (main_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create loop frame script file %s - exiting\n", main_file); @@ -2664,5 +2670,8 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { Return (GMT_RUNTIME_ERROR); } + if (current_error) /* Force removal of work dir since job failed */ + system (zap_workdir); + Return (current_error); } From 8a2b4ae60a73d41523f73b77f35b7136fc222da2 Mon Sep 17 00:00:00 2001 From: Paul Wessel Date: Tue, 16 Nov 2021 12:07:59 -1000 Subject: [PATCH 4/4] use abs path to cleanup script and make it hidden SHould work now. --- doc/rst/source/batch.rst | 2 +- doc/rst/source/movie.rst | 2 +- src/batch.c | 4 ++-- src/movie.c | 7 ++++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/rst/source/batch.rst b/doc/rst/source/batch.rst index 3de6666a658..7dc320c42e1 100644 --- a/doc/rst/source/batch.rst +++ b/doc/rst/source/batch.rst @@ -219,7 +219,7 @@ The **batch** module creates several hidden script files that are used in the ge (initializes variables related to the overall batch job and includes the contents of the optional *includefile*), *batch_preflight* (optional since it derives from **-Sb** and computes or prepares needed data files), *batch_postflight* (optional since it derives from **-Sf** and processes files once all the batch job complete), *batch_job* -(accepts a job counter argument and processes data for those parameters), and *batch_cleanup* (removes temporary +(accepts a job counter argument and processes data for those parameters), and a hidden *batch_cleanup* (removes temporary files at the end of the process). For each job, there is a separate *batch_params_######* script that provides job-specific variables (e.g., job number and anything given via **-T**). The *preflight* and *postflight* scripts have access to the information in *batch_init*, while the *batch_job* script in addition has access to the job-specific diff --git a/doc/rst/source/movie.rst b/doc/rst/source/movie.rst index 13e4c3a86ca..851377b187a 100644 --- a/doc/rst/source/movie.rst +++ b/doc/rst/source/movie.rst @@ -420,7 +420,7 @@ scripting language used): *movie_init* (initializes variables related to canvas and includes the contents of the optional *includefile*), *movie_preflight* (optional since it derives from **-Sb** and computes needed data files and possibly a background layer), *movie_postflight* (optional since it derives from **-Sf** and builds a foreground layer), *movie_frame* (accepts a frame counter -argument and builds the frame image), and *movie_cleanup* (removes temporary files at the end of the +argument and builds the frame image), and a hidden *movie_cleanup* (removes temporary files at the end of the run). For each frame there is a separate *movie_params_######* script that provides frame-specific variables (e.g., frame number and anything given via **-T**). The pre- and post-flight scripts have access to the information in *movie_init* while the frame script in addition has access to the frame-specific diff --git a/src/batch.c b/src/batch.c index 5e823cef465..9893cd993ad 100644 --- a/src/batch.c +++ b/src/batch.c @@ -561,7 +561,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { sprintf (main_file, "batch_job.%s", extension[Ctrl->In.mode]); /* Prepare the cleanup script */ - sprintf (cleanup_file, "batch_cleanup.%s", extension[Ctrl->In.mode]); + sprintf (cleanup_file, "%s/batch_cleanup_%d.%s", API->tmp_dir, (int)getpid(), extension[Ctrl->In.mode]); GMT_Report (API, GMT_MSG_INFORMATION, "Create cleanup script %s\n", cleanup_file); if ((fp = fopen (cleanup_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create cleanup file %s - exiting\n", cleanup_file); @@ -1005,7 +1005,7 @@ EXTERN_MSC int GMT_batch (void *V_API, int mode, void *args) { } /* Finally, delete the clean-up script separately since under DOS we got complaints when we had it delete itself (which works under *nix) */ - if (!Ctrl->Q.active && gmt_remove_file (GMT, cleanup_file)) { /* Delete the cleanup script itself */ + if (gmt_remove_file (GMT, cleanup_file)) { /* Delete the cleanup script itself */ GMT_Report (API, GMT_MSG_ERROR, "Unable to delete the cleanup script %s.\n", cleanup_file); Return (GMT_RUNTIME_ERROR); } diff --git a/src/movie.c b/src/movie.c index 7b35a878680..23742441d19 100644 --- a/src/movie.c +++ b/src/movie.c @@ -1584,7 +1584,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { sprintf (main_file, "movie_frame.%s", extension[Ctrl->In.mode]); /* Prepare the cleanup script */ - sprintf (cleanup_file, "movie_cleanup.%s", extension[Ctrl->In.mode]); + sprintf (cleanup_file, "%s/movie_cleanup_%d.%s", API->tmp_dir, (int)getpid(), extension[Ctrl->In.mode]); if ((fp = fopen (cleanup_file, "w")) == NULL) { GMT_Report (API, GMT_MSG_ERROR, "Unable to create cleanup file %s - exiting\n", cleanup_file); Return (GMT_ERROR_ON_FOPEN); @@ -2449,6 +2449,7 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { sprintf (htxt, ",H%d", Ctrl->H.factor); strcat (extra, htxt); } + gmt_set_script (fp, Ctrl->In.mode); /* Write 1st line of a script */ gmt_set_comment (fp, Ctrl->In.mode, "Main frame loop script"); fprintf (fp, "%s", export[Ctrl->In.mode]); /* Hardwire a GMT_SESSION_NAME since sub-shells may mess things up */ @@ -2665,12 +2666,12 @@ EXTERN_MSC int GMT_movie (void *V_API, int mode, void *args) { } /* Finally, delete the clean-up script separately since under DOS we got complaints when we had it delete itself (which works under *nix) */ - if (!Ctrl->Q.active && gmt_remove_file (GMT, cleanup_file)) { /* Delete the cleanup script itself */ + if (gmt_remove_file (GMT, cleanup_file)) { /* Delete the cleanup script itself */ GMT_Report (API, GMT_MSG_ERROR, "Unable to delete the cleanup script %s.\n", cleanup_file); Return (GMT_RUNTIME_ERROR); } - if (current_error) /* Force removal of work dir since job failed */ + if (Ctrl->Q.active && current_error) /* Force removal of work dir since job failed */ system (zap_workdir); Return (current_error);