Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Silent fail on impossible file write #553

Closed
jcoupey opened this issue Aug 10, 2021 · 6 comments · Fixed by #933
Closed

Silent fail on impossible file write #553

jcoupey opened this issue Aug 10, 2021 · 6 comments · Fixed by #933

Comments

@jcoupey
Copy link
Collaborator

jcoupey commented Aug 10, 2021

Suppose we have an input.json file in the current directory and foo is not a valid directory. Then

vroom -i input.json -o foo/output.json

fails to write any output. The return code is 0, which is somehow consistent with exiting silently.

We should really raise an error when writing to a file is requested and turns out to be impossible.

@rsh-raj
Copy link

rsh-raj commented Aug 10, 2021

Hey, I will like to work on it. Can you please tell the file name in which I have to make changes.

@jcoupey
Copy link
Collaborator Author

jcoupey commented Aug 11, 2021

@rsh-raj thanks for considering this!

Writing the solution (or any other error message) happens in the write_to_json function:

// Write to relevant output.
if (output_file.empty()) {
// Log to standard output.
std::cout << s.GetString() << std::endl;
} else {
// Log to file.
std::ofstream out_stream(output_file, std::ofstream::out);
out_stream << s.GetString();
out_stream.close();
}

But throwing an exception there would not be of much help. Indeed, we have a number of try clauses in main.cpp for various errors and the catch part usually calls write_to_json for errors too, expecting the output file to be valid. For example, the high-level calls for parsing/solving/writing are:

vroom/src/main.cpp

Lines 177 to 196 in 7be0b4f

try {
// Build problem.
vroom::Input problem_instance = vroom::io::parse(cl_args);
vroom::Solution sol = (cl_args.check)
? problem_instance.check(cl_args.nb_threads)
: problem_instance.solve(cl_args.exploration_level,
cl_args.nb_threads,
cl_args.h_params);
// Write solution.
vroom::io::write_to_json(sol, cl_args.geometry, cl_args.output_file);
} catch (const vroom::Exception& e) {
auto error_code = vroom::utils::get_code(e.error);
std::cerr << "[Error] " << e.message << std::endl;
vroom::io::write_to_json({error_code, e.message},
false,
cl_args.output_file);
exit(error_code);
}

So I think our best bet would be to check for a valid output file right after all flags are parsed. I'm not very familiar with output streams and file handling but it looks like std::ofstream objects have a fail member function.

@jcoupey jcoupey added this to the v1.12.0 milestone Mar 29, 2022
@erdemuysal
Copy link
Contributor

@jcoupey
I think there are decision to be made. After making these decisions, I will try to do my best.

  1. Should we a) check before try to write? b) catch exception after trying to write?
  2. If directory not exist: a) should it be created? b) raise an error? c) fall back to stdout?
  3. Should we check permission to create a file also?

The method I would suggest is to create a validation function to vroom::io that validate permission and existence, then check right after the arguments are parsed. If invalid to write an output then fallback to the standard output. (1-a, 2-c, 3)

@jcoupey
Copy link
Collaborator Author

jcoupey commented Apr 11, 2022

@erdemuysal thanks for stepping up on this one too!

Should we a) check before try to write? b) catch exception after trying to write?

I agree a) would be better here since we'd then avoid performing routing requests and solving the problem for nothing.

If directory not exist: a) should it be created? b) raise an error? c) fall back to stdout?

Deciding to create a non-existing directory on behalf of the user running vroom sounds a bit extreme. Most command-line tools raise an error when trying to operate on missing directories so I'd go for b).
Option c) would require users to be fully aware of the default fallback, and means they'd have to check both the expected file or stdout when solving which IMHO adds complexity. Also having some unexpected json output appear on stdout may break some existing workflows when doing batch solving in scripts where the rest of the output is used. For example on our benchmark workflow or when solving with -DLOG_LS_OPERATORS to output debug information.

Should we check permission to create a file also?

As you suggest, catching a permission problem should probably be part of the check from point 1.

The method I would suggest is to create a validation function to vroom::io that validate permission and existence, then check right after the arguments are parsed. If invalid to write an output then fallback to the standard output. (1-a, 2-c, 3)

I'd keep this summary except I'd simply exit without doing anything in case writing to the requested file is impossible. You can have your vroom::io validation function throw a vroom::InputException in that case and simply catch that in main like here.

@jcoupey jcoupey modified the milestones: v1.12.0, v1.13.0 May 11, 2022
@jcoupey
Copy link
Collaborator Author

jcoupey commented Nov 28, 2022

Moving this to the next milestone again. Maybe that would be a good opportunity to switch to using the std::filesystem support added in C++17.

@jcoupey jcoupey modified the milestones: v1.13.0, v1.14.0 Nov 28, 2022
@jcoupey
Copy link
Collaborator Author

jcoupey commented Jun 21, 2023

switch to using the std::filesystem support added in C++17

Additionally, we could provide a better feedback for a missing input file. The current (cryptic) error is:

$ vroom -i foo.json
[Error] The document is empty. (offset: 0)
{"code":2,"error":"The document is empty. (offset: 0)"}

@jcoupey jcoupey mentioned this issue Jun 21, 2023
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants