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

Write EPIPE errors for certain png images #69

Closed
geraldke opened this issue Jul 18, 2020 · 3 comments
Closed

Write EPIPE errors for certain png images #69

geraldke opened this issue Jul 18, 2020 · 3 comments

Comments

@geraldke
Copy link

geraldke commented Jul 18, 2020

I'm getting the following error for certain png images:

at WriteWrap.onWriteComplete [as oncomplete] (internal/stream_base_commons.js:87:16)
(node:4546) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)

This seems to be happening only on linux machines. I can't replicate this on a Mac because it uses a different binary.

I've also tried identifying the problematic image with ImageMagick, I'm not seeing anything odd on the output:
https://gist.github.com/geraldke/68f2e5f6480fdf18472286b73c01dfc3

Here's a test repo that can reproduce the error. Steps are on the readme, problematic image included.
https://github.com/geraldke/imagemin-pngquant-issue

It's odd that running the binary directly succeeds:

./node_modules/pngquant-bin/vendor/pngquant -- images/test.png

might be related to: #68

@Juddling
Copy link

Reproduced on an Ubuntu 18.04 system, when ran with strace we can see:

write(18, "\211PNG\r\n\32\n\0\0\0\rIHDR\0\0\4\0\0\0\3\0\10\0\0\0\0\237\321J"..., 470854) = 255808
write(18, " \342\326\353+\254\250b\2578|8\327\247\f\357\37\364B\251\302\240\"\4\216\244\314Q\310\320\277\371"..., 215046) = -1 EAGAIN (Resource temporarily unavailable)
write(18, " \342\326\353+\254\250b\2578|8\327\247\f\357\37\364B\251\302\240\"\4\216\244\314Q\310\320\277\371"..., 215046) = 182720
write(18, "7\237\370S\372\256\334\237\336\373\311\237\372\21\273\274\365a\363C\364\357\376\310/\376}\370\324\337\375\341"..., 32326) = -1 EPIPE (Broken pipe)

Which shows a partially successful write, EAGAIN, another partial write, and then EPIPE

@Juddling
Copy link

Juddling commented Jul 22, 2020

Turns out the png image is invalid 🤦 No fixes are required for this package.

# pngcheck test.png
test.png  additional data after IEND chunk
ERROR: test.png

For anyone interested in what's going on under the hood: the image is piped to the stdin of the child process running pngquant, when this pipe is created, a flag is set:

socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, [18, 19]) = 0

SOCK_CLOEXEC this closes the pipe as soon as the child process has executed.

The order of events is:

  • create the socket pair
  • begin writes of image content to socket (and continue trying, note the partial writes shown in previous comment)
  • subprocess begins
  • subprocess completes and exits (it sees the IEND png chunk so has no idea there is more data)
  • pipe is closed due to SOCK_CLOEXEC flag
  • next write of image content to pipe files because pipe is closed, hence EPIPE

@geraldke
Copy link
Author

@Juddling That makes perfect sense! Closing this off then, thanks!

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

2 participants