[
https://issues.apache.org/jira/browse/IO-729?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17420328#comment-17420328
]
Rob Spoor commented on IO-729:
------------------------------
[~ggregory] I hadn't thought of a solution yet, I merely stated an issue. The
throwing of the {{exception}} field in {{close()}} is the root of this issue.
Possible solutions:
* Add a flag, set in the constructor and defaulting to {{false}}, to omit
throwing from {{close()}}. This would mean that {{close()}} would never throw
an exception if the flag is set.
* Add a flag, set by any other method, to omit throwing from {{close}}. This
would mean that {{close}} would only throw an exception if no other method
caused an exception. This may break expected behaviour.
* Replace the {{exception}} field with a {{Supplier<IOException>}}. A new
constructor needs to be added that takes a {{Supplier<IOException>}} instead of
an {{IOException}}. The existing constructors need to be updated, for example:
{code} public BrokenOutputStream(final IOException exception) {
this(() -> exception);
}
public BrokenOutputStream() {
this(() -> new IOException("Broken output stream")); // causes a new
exception to be used for each method call
}{code}
----
The first option is the simplest, but requires calling a different constructor
when try-with-resources is used.
The second option is my least favourite, as it may cause issues with people
expecting {{close()}} to throw an exception even if another method already
threw one (these people are then not using try-with-resources).
The third option is my preferred choice, as provides the most flexibility.
There is a change in behaviour if the non-argument constructor is called; each
method will throw a different exception. Except when the constructor that takes
an {{IOException}} is used, it does lead to a working try-with-resources block
though, that will fail with an {{IOException}} and not an
{{IllegalArgumentException}}. The {{IOException}} will have a suppressed
{{IOException}} from the call to {{close()}}.
I'd like to hear your thoughts on this.
> BrokenReader, BrokenWriter, BrokenInputStream, BrokenOutputStream can cause
> IllegalArgumentException in combination with try-with-resources
> -------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: IO-729
> URL: https://issues.apache.org/jira/browse/IO-729
> Project: Commons IO
> Issue Type: Bug
> Components: Streams/Writers
> Affects Versions: 2.8.0
> Reporter: Rob Spoor
> Priority: Minor
>
> The following little code snippet can cause an IllegalArgumentException with
> message "Self-suppression not permitted":
> {code} try (Writer writer = new BrokenWriter()) {
> writer.write('a');
> }{code}
> The try-with-resources mechanism will try to add the exception thrown from
> {{close}} as suppress exception to the exception thrown from {{write}}. Since
> those are the same, an exception is thrown. From the source of
> java.lang.Throwable:
> {code} public final synchronized void addSuppressed(Throwable exception) {
> if (exception == this)
> throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE,
> exception);{code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)