Repository: pinojs/pino (js)

Issue:
"EAGAIN: resource temporarily unavailable, write" on fatal
Before https://github.com/pinojs/pino/pull/730, the use of `fatal` was safe.
After that version, my application crash with `EAGAIN: resource temporarily unavailable, write`.

The linked lines live in sonicboom repo:

https://github.com/mcollina/sonic-boom/blob/e1b31fb93c5a8c306cdc16021e81b4995056a5aa/index.js#L245-L248

This behaviour was considered a patch but the behaviour changes.

Can I may send a PR with a patch (maybe a configuration flag)?

Pull request description:
catch potential write errors on fatal flush sync
fix #739 

This PR allows the developer to choose if flush sync on fatal.
The default is `false`

Bench:
## this branch
```
% npm run bench-basic

> pino@5.13.6 bench-basic /Users/tommasoallevi/Downloads/repo/pino
> node benchmarks/utils/runbench basic

Running BASIC benchmark

benchBunyan*10000: 482.314ms
benchWinston*10000: 364.687ms
benchBole*10000: 348.318ms
benchDebug*10000: 225.755ms
benchLogLevel*10000: 216.953ms
benchPino*10000: 460.753ms
benchPinoExtreme*10000: 185.467ms
benchPinoNodeStream*10000: 175.491ms
benchBunyan*10000: 408.892ms
benchWinston*10000: 283.859ms
benchBole*10000: 181.260ms
benchDebug*10000: 225.092ms
benchLogLevel*10000: 203.503ms
benchPino*10000: 395.198ms
benchPinoExtreme*10000: 178.076ms
benchPinoNodeStream*10000: 148.326ms

==========
BASIC benchmark averages
Bunyan average: 445.603ms
Winston average: 324.273ms
Bole average: 264.789ms
Debug average: 225.423ms
LogLevel average: 210.228ms
Pino average: 427.976ms
PinoExtreme average: 181.772ms
PinoNodeStream average: 161.909ms
==========
System: Darwin/darwin x64 19.0.0 ~ Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz (cores/threads: 8)
```

## master
```
% npm run bench-basic

> pino@5.13.6 bench-basic /Users/tommasoallevi/Downloads/repo/pino
> node benchmarks/utils/runbench basic

Running BASIC benchmark

benchBunyan*10000: 465.974ms
benchWinston*10000: 371.409ms
benchBole*10000: 363.848ms
benchDebug*10000: 235.101ms
benchLogLevel*10000: 216.776ms
benchPino*10000: 389.143ms
benchPinoExtreme*10000: 184.884ms
benchPinoNodeStream*10000: 165.704ms
benchBunyan*10000: 392.238ms
benchWinston*10000: 286.630ms
benchBole*10000: 172.467ms
benchDebug*10000: 223.721ms
benchLogLevel*10000: 204.255ms
benchPino*10000: 389.809ms
benchPinoExtreme*10000: 190.509ms
benchPinoNodeStream*10000: 147.684ms

==========
BASIC benchmark averages
Bunyan average: 429.106ms
Winston average: 329.019ms
Bole average: 268.158ms
Debug average: 229.411ms
LogLevel average: 210.516ms
Pino average: 389.476ms
PinoExtreme average: 187.696ms
PinoNodeStream average: 156.694ms
==========
System: Darwin/darwin x64 19.0.0 ~ Intel(R) Core(TM) i5-8279U CPU @ 2.40GHz (cores/threads: 8)
```

Patch:
diff --git a/lib/levels.js b/lib/levels.js
index a9e0e55..c4ebbdc 100644
--- a/lib/levels.js
+++ b/lib/levels.js
@@ -24,7 +24,11 @@ const levelMethods = {
     const stream = this[streamSym]
     logFatal.call(this, ...args)
     if (typeof stream.flushSync === 'function') {
-      stream.flushSync()
+      try {
+        stream.flushSync()
+      } catch (e) {
+        // https://github.com/pinojs/pino/pull/740#discussion_r346788313
+      }
     }
   },
   error: genLog(levels.error),


Test patch:
diff --git a/test/levels.test.js b/test/levels.test.js
index 4643ad8..b7ac1cc 100644
--- a/test/levels.test.js
+++ b/test/levels.test.js
@@ -417,3 +417,16 @@ test('fatal method sync-flushes the destination if sync flushing is available',
     instance.fatal('this is fatal')
   })
 })
+
+test('fatal method should call async when sync-flushing fails', ({ equal, fail, doesNotThrow, plan }) => {
+  plan(2)
+  const messages = [
+    'this is fatal 1'
+  ]
+  const stream = sink((result) => equal(result.msg, messages.shift()))
+  stream.flushSync = () => { throw new Error('Error') }
+  stream.flush = () => fail('flush should be called')
+
+  const instance = pino(stream)
+  doesNotThrow(() => instance.fatal(messages[0]))
+})