Write a program or function with the following functionality:
- The program/function first attempts to write the string
Hello, world!to the standard output stream. (No other forms of output are acceptable for this challenge, as the focus is very much on the I/O rather than the trivial behaviour of the program itself.) Depending on whether it succeeded:- If it succeeded in outputting
Hello, world!, the program/function exits without any further behaviour. - If it failed to produce the correct output due to an error, the program/function attempts to write the string
Error writing "Hello, world!"to the standard error stream. (For the purposes of this challenge, you don't need error handling for the error handling itself.)
- If it succeeded in outputting
Clarifications
Your program/function will be run with no input (unless it's written in a language which absolutely requires input to work, in which case it will be run with the simplest possible input).
When producing output, you may also produce a single trailing newline if you wish, but doing so is not mandatory.
The definition of "error writing to standard output" that your program implements must treat at least the following cases as errors:
- Standard output being nonexistent (i.e.
stdoutis a closed filehandle, no file descriptor 1 exists, or however those cases translate to the language and OS you're using); - Standard output referring to a file on a disk that has no free space left;
- Standard output connecting to another program, which has already closed its end of the connection.
and must treat at least the following cases as success (i.e. not an error):
- Standard output connects to a terminal, and
Hello, world!is displayed onscreen. - Standard output connects to a file, and
Hello, world!is written into the file.
You can choose the details of what counts as an output error, so long as it's consistent with the above rules.
- Standard output being nonexistent (i.e.
Your program/function should not crash upon encountering any of the error situations listed above. It's up to you what exit code you use.
Your program/function should not describe the nature of the encountered error on the standard error stream; it should just print the string specified above. Extraneous output on standard error (e.g. compiler warnings) is only legal if it's produced unconditionally, regardless of whether an error is encountered or not.
Your program only needs to work on one operating system (although it must be one on which the errors listed above make sense; I've tried to keep them general enough to work on most multitasking consumer operating systems, but weirder operating systems may well be excluded from this challenge). If your program is nonportable, list the assumptions it needs to run in the title of your submission.
This task may not be possible in every language (not every language allows a program to handle output errors in a custom way). You'll have to pick a language where it is possible.
Make sure that your program/function works! Don't just trust the documentation of library functions to do what they say they do. The error handling of simple output functions often turns out to be broken in practice, even if the functions claim to handle errors in theory.
Test cases
Here's a way to simulate each of the error conditions above using bash on Linux (you don't have to use Linux, but it's likely the easiest system to test this on):
your_program_here >&- # nonexistent stdout
your_program_here > /dev/full # out of disk space
mkfifo test # note: change "test" to a filename that isn't in use
true < test &
your_program_here > test # connecting to a program that doesn't want input
rm test # clean up the FIFO we used earlier
The first two testcases are deterministic. The last isn't (it relies on a race condition); for testing purposes, I recommend adding a delay between the start of your program and the actual output to standard output, in order to ensure that the race condition is resolved in the way that exposes the error.
Victory condition
This is a code-golf challenge, so shorter is better. As (nearly) always, we're measuring the length of the program in bytes.
10 Answers 10
Bash, (削除) 71 (削除ここまで) 60 bytes
h=Hello,\ world!
(echo $h)2>&-||echo Error writing \"$h\">&2
How it works
After saving Hello, world! to the variable h, we do the following.
First, (echo $h)2>&- attempts to print Hello, world! to STDOUT. 2>&- is required to prevent displaying the error message echo: write error: Bad file descriptor in case the write fails. Since writing to a named pipe that doesn't accept input would kill the Bash program with signal 13 (SIGPIPE), we execute the command in a subshell ((...)), so only the subshell will get killed.
Finally, if printing to STDOUT failed, the subshell will exit with a non-zero status code (141 for SIGPIPE, 1 for a generic error), so echo Error writing \"$h\">&2 prints the desired message to STDERR.
C (gcc), (削除) 87 (削除ここまで) 86 bytes
f(){signal(13,1);write(1-puts("Hello, world!"),"Error writing \"Hello, world!\"",29);}
Ungolfed
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void f(void)
{
signal(SIGPIPE, SIG_IGN); // Works (and is required) on TIO. YMMV
int fd = (puts("Hello, world!")) < 0 ? 2 : -13;
write(fd, "Error writing \"Hello, world!\"", 29);
}
-
\$\begingroup\$ how do you know what return puts? here says just it is >=0 for to be all ok... \$\endgroup\$user58988– user589882017年04月12日 18:51:45 +00:00Commented Apr 12, 2017 at 18:51
-
\$\begingroup\$
putsreturns the number of bytes that have been written or -1 in case of an error, so it either returns 14 (Hello World plus newline) or -1. (That may be platform-specific, but this is how it behaves with glibc.) \$\endgroup\$Dennis– Dennis2017年04月12日 18:53:24 +00:00Commented Apr 12, 2017 at 18:53 -
\$\begingroup\$ K&R2 says it return EOF [-1 praticly] if error; or a value not negative if all ok \$\endgroup\$user58988– user589882017年04月12日 19:08:25 +00:00Commented Apr 12, 2017 at 19:08
-
1\$\begingroup\$ On PPCG, languages are defined by their implementation, and gcc/glibc behave like I said they do. \$\endgroup\$Dennis– Dennis2017年04月12日 19:15:07 +00:00Commented Apr 12, 2017 at 19:15
-
\$\begingroup\$ i prefer the old book \$\endgroup\$user58988– user589882017年04月12日 19:16:32 +00:00Commented Apr 12, 2017 at 19:16
C, 77 bytes
f(a){a="Error writing \"Hello, world!\"";write(1,a+15,13)-13&&write(2,a,29);}
for call
main(){f(1); return 0;}
-
\$\begingroup\$ On which platform did you test this? It doesn't work on Linux if a broken pipe is encountered. \$\endgroup\$Dennis– Dennis2017年04月12日 19:31:49 +00:00Commented Apr 12, 2017 at 19:31
PowerShell, 80 Bytes
try{echo($h="Hello, World!") -ea 4}catch{$host.ui|% *rL* "Error writing ""$h"""}
explained:
try{
#Attempt to 'echo' (write output) the string, and assign it to $h
#Make sure the 'error action' is set to '4' to make it a terminating error.
echo($h="Hello, World!") -ea 4
} catch {
#Use the "WriteErrorLine" function in $host.ui to stderr
$host.ui|% *rL* "Error writing ""$h"""
}
haven't managed to actually try this when it errors, but it definitely ~should~ work.
-
\$\begingroup\$ The error message should be written to STDERR. Writing it to STDOUT isn't possible if an error occurs during the first write attempt. \$\endgroup\$Dennis– Dennis2017年04月12日 16:27:49 +00:00Commented Apr 12, 2017 at 16:27
-
\$\begingroup\$ @Dennis thanks for that, updated there, didn't read the question fully. \$\endgroup\$colsw– colsw2017年04月12日 21:37:42 +00:00Commented Apr 12, 2017 at 21:37
-
\$\begingroup\$ Afaict PowerShell only catches fatal exceptions, so you'd need
Write-Host -ErrorAction Stopor something like that. Also, thethrowproduces additional debugging ingormation apart of the line it should print, which by the way should have a lowercase W and double quotes around the HW string. \$\endgroup\$Dennis– Dennis2017年04月12日 22:19:29 +00:00Commented Apr 12, 2017 at 22:19 -
\$\begingroup\$ @Dennis the additional debug info has crushed me, answer updated there now. \$\endgroup\$colsw– colsw2017年04月13日 15:44:55 +00:00Commented Apr 13, 2017 at 15:44
Perl 5, 51 bytes
requires -M5.01, which is free
say$h="Hello, world!"or die"Error writing \"$h\"$/"
Tested in Strawberry Perl 5.24.0 by running the program as-is (printed to standard output) and by running
print f $h="Hello, world!"or die"Error writing \"$h\"$/"
(printed to standard error). I don't know how to test for other errors using Strawberry, but they should be handled the same....
-
\$\begingroup\$ As far as I can tell, this doesn't work. tio.run/nexus/bash#jY3NDoIwEITvfYq1IXCiiD83ys3Ei2/… (The string is also missing a comma.) \$\endgroup\$Dennis– Dennis2017年04月12日 06:24:49 +00:00Commented Apr 12, 2017 at 6:24
-
\$\begingroup\$ I don't know what to make of that page you linked to; can you explain, please? Also, note that the script needs to work on one OS only. And I'll add the comma; thanks. \$\endgroup\$msh210– msh2102017年04月12日 06:27:14 +00:00Commented Apr 12, 2017 at 6:27
-
\$\begingroup\$ Output should display
Hello, world!after=== 1 ===and nothing after the others. Debug should display nothing after=== 1 ===andError writing "Hello, world!"after the others. I'm aware that your program doesn't have to work on TIO, butprint f...shows the intended error messages while the original program does not. \$\endgroup\$Dennis– Dennis2017年04月12日 06:31:15 +00:00Commented Apr 12, 2017 at 6:31 -
\$\begingroup\$ "Output" and "Debug" both display nothing as far as I see. I also don't know what the "Header" and "Footer" sections are supposed to be. And I'm wholly unfamiliar with TIO, but note that Strawberry Perl runs on MS Windows. \$\endgroup\$msh210– msh2102017年04月12日 06:37:00 +00:00Commented Apr 12, 2017 at 6:37
-
REXX, (削除) 111 (削除ここまで) 106 bytes
signal on notready
a='Hello, world!'
_=lineout(,a)
exit
notready:_=lineout('stderr','Error writing "'a'"')
The program relies on there being a stream called 'stderr'. This will probably not be the case on IBM systems.
Javascript, (削除) 79 (削除ここまで) 76 bytes
try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}
-
\$\begingroup\$ Note that the string you should output is
'Hello, world!', which is one byte longer than what you use. Also, I suppose assigningainside the call toconsole.logwould be shorter (1B) and removing the semicolon afterl.log(a)saves another byte. \$\endgroup\$Luke– Luke2017年04月12日 15:05:56 +00:00Commented Apr 12, 2017 at 15:05 -
\$\begingroup\$ @Luke Thanks, That was quite a big mistake! \$\endgroup\$Matthew Roh– Matthew Roh2017年04月12日 15:08:46 +00:00Commented Apr 12, 2017 at 15:08
-
1\$\begingroup\$
try{(l=console).log(a="Hello, world!")}catch(e){l.error('Error writing '+a)}for 76 bytes. First,consoleis assigned tol, then"Hello, world!'is assigned toa, and then it's executed. \$\endgroup\$Luke– Luke2017年04月12日 15:10:02 +00:00Commented Apr 12, 2017 at 15:10
R, 91 bytes
s="Hello, world!"
tryCatch(cat(s),error=function(e)cat('Error writing "','"',file=2,sep=s))
I tried erroring it by running it with cat(s,file=12) instead of cat(s), and it prints the correct text to stderr. This is an invalid connection error otherwise.
-
\$\begingroup\$ Any idea how to test for other output errors? \$\endgroup\$JayCe– JayCe2018年07月13日 19:17:07 +00:00Commented Jul 13, 2018 at 19:17
sleep 1 < test; (sleep 2; your_program_here) > test? \$\endgroup\$