I am using a ffi for nodejs which for the most part has nothing to do with this question which is really about understanding pipes better, but does offer some contextfunction exec(cmd) {  var buffer = new Buffer(32);  var result = '';  var fp = libc.popen('( ' + cmd + ') 2>&1', 'r');  var code;  if (!fp) throw new Error('execSync error: '+cmd);  while( !libc.feof(fp) ){    libc.fgets(buffer, 32, fp)    result += buffer.readCString();  }  code = libc.pclose(fp) >> 8;  return {    stdout: result,    code: code  };}which brings me to this bit of code that when i run using this exec function  tr -dc [:alpha:] < /dev/urandom | head -c ${1-8}I get the error write error: Broken pipetr: write errorbut I do get the output I expect 8 random numbers, this confused the hell out of me but then in some wild googling I found this stack answer which perfectly fit my situation.I am left with these questions though...Why does tr -dc [:alpha:] < /dev/urandom | head -c ${1-8}throw a broken pipe error when called with my exec command but not when called from the shell. I don`t understand why when I call tr -dc [:alpha:] < /dev/urandomit reads endlessly but when I pipe it to head -c ${1-8}It works with out throwing a broken pipe error. It seems that head would take what it needs and tr would just read for ever. At least it should throw broken pipe, head would consume the first 8 bytes and then tr would still be putting out output and broken pipe would be thrown by tr because head has stopped running. Both situations make sense to me but it seems that they are some what exclusive to each other. I don`t understand what is different between calling exec(tr -dc [:alpha:] < /dev/urandom | head -c ${1-8})and tr -dc [:alpha:] < /dev/urandom | head -c ${1-8}directly from the command lineand specifically why < an endless file into something and then | it to something makes it not run endlessly, ive been doing this for years and never questioned why it works this way. Lastly is it ok to ignore this broken pipe err? Is there a way to fix it am I doing something wrong in my c++ ish javascript code. Am I missing some kind of popen basics?------ EDITmessing around some more the codeexec('head -10 /dev/urandom | tr -dc [:alpha:] | head -c 8')throws no pipe error!
broken pipe error with popen and JS ffi
shell;pipe
Normally, tr shouldn't be able to write that error message because it should have been killed by a SIGPIPE signal when trying to write something after the other end of the pipe has been closed upon termination of head.You get that error message because somehow, the process running tr has been configured to ignore SIGPIPEs. I suspect that might be done by the popen() implementation in your language there.You can reproduce it by doing:sh -c 'trap  PIPE; tr -dc [:alpha:] < /dev/urandom | head -c 8'You can confirm that's what is happening by doing:strace -fe signal sh your-program(or the equivalent on your system if not using Linux). You'll then see something like:rt_sigaction(SIGPIPE, {SIG_IGN, ~[RTMIN RT_1], SA_RESTORER, 0x37cfc324f0}, NULL, 8) = 0orsignal(SIGPIPE, SIG_IGN)done in one process before that same process or one of its descendants executes the /bin/sh that interprets that command line and starts tr and head.If you do a strace -fe write, you'll see something like:write(1, AJiYTlFFjjVIzkhCAhccuZddwcydwIIw..., 4096) = -1 EPIPE (Broken pipe)The write system call fails with an EPIPE error instead of triggering a SIGPIPE.In any case tr will exit. When ignoring SIGPIPE, because of that error (but that also triggers an error message). When not, it exits upon receiving the SIGPIPE. You do want it to exit, since you don't want it carrying on reading /dev/urandom after those 8 bytes have been read by head.To avoid that error message, you can restore the default handler for SIGPIPE with:trap - PIPEPrior to calling tr:popen(trap - PIPE; { tr ... | head -c 8; } 2>&1, ...)