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

fmt::print() throwing on file IO errors should at least be clearly documented #3637

Closed
madscientist opened this issue Sep 13, 2023 · 5 comments

Comments

@madscientist
Copy link

IMO having fmt::print() throw an exception on file IO errors is problematic. It makes switching from fprintf() to fmt::print() dangerous, in a potentially non-obvious way.

I suppose it's too late now to reconsider the API for fmt::print(), but it would be good to add a note to the documentation making it clear that these methods throw an exception on file IO errors (and which exception is thrown), in addition to the expected exception thrown on formatting errors.

@vitaut
Copy link
Contributor

vitaut commented Sep 16, 2023

Good idea, documented in aa3c5a4. Migration from printf is not the main goal and printf's error handling is obviously bad. You could introduce your functions for migration purposes and handle errors differently.

@vitaut vitaut closed this as completed Sep 16, 2023
@madscientist
Copy link
Author

I don't really agree that printf()'s error handling is obviously bad. In my experience, it's virtually always true that programs want to ignore errors returned by printf(). For example if your program generates output and the user decides to send that output to a pipe, then the program on the other side closes the pipe, you usually don't want your program to terminate, or even to exit early. You simply want to ignore that error and continue on as if it didn't happen. Having to add a try/catch block around each print() call is clearly annoying. I've seen various design standards such as the GNU standards, which recommend waiting until the end of the processing and checking to see if any IO errors were thrown and if so, then providing some diagnostics (of course if both stdout and stderr are closed there's not much you can provide in the way of diagnostics).

I think the issue is more, where is the output going? If it's printf() (going to stdout) or fprintf(stderr, ...) then you almost always want to ignore errors in the IO. If it's going to some other file that the user created, you probably don't want to ignore it.

I ended up creating this template and using this everywhere that I am trying to print to stdout/stderr:

template <typename... Args>
inline int fmtprint(FILE* fp, fmt::format_string<Args...> fmt, Args&&... args)
{
    return fputs(fmt::vformat(fmt, fmt::make_format_args(args...)).c_str(), fp);
}

(and another one to call without FILE*).

@vitaut
Copy link
Contributor

vitaut commented Sep 18, 2023

I think it's specific to your application but as a general default easily ignorable error handling is a non-starter. In any case as you've already discovered it's easy to implement a different error handling.

@torsten48
Copy link
Contributor

Does this mean fmt::print() throws if e.g. on Windows a process is detached (runs without console) ?

@vitaut
Copy link
Contributor

vitaut commented May 3, 2024

If WriteConsole fails in this case then yes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants