# # # delete "tests/log_quits_on_SIGPIPE/hookfile" # # patch "tests/log_quits_on_SIGPIPE/__driver__.lua" # from [516da7ffcbf62fcbe923784a6a1d11bedbb553e2] # to [058dba7d455d1d84269b4f9e884775d2ef4dac13] # ============================================================ --- tests/log_quits_on_SIGPIPE/__driver__.lua 516da7ffcbf62fcbe923784a6a1d11bedbb553e2 +++ tests/log_quits_on_SIGPIPE/__driver__.lua 058dba7d455d1d84269b4f9e884775d2ef4dac13 @@ -6,73 +6,78 @@ SIGPIPE = 13 -- what it is on traditiona skip_if(ostype=="Windows") SIGPIPE = 13 -- what it is on traditional Unixy systems -mtn_setup() -addfile("file", "This is a file") -commit() - -- Testing this correctly involves avoiding a number of race --- conditions. This is how we used to try to do it: +-- conditions. This is the behavior we want: -- -- parent child -- ------ ----- -- fork -- exec --- open pipe for write --- kill(child, SIGPIPE) --- --- But it is entirely possible for the parent to complete all of the --- actions on its side before the child has set up signal handlers, --- and SIGPIPE may be being ignored, so the signal gets lost. Also, --- this is not really testing what we want to test, which is behavior --- on delivery of a real SIGPIPE by the kernel. So we want to do this --- instead: --- --- parent child --- ------ ----- --- fork --- exec --- open pipe for write --- open pipe for read +-- open pipe for read open pipe for write +-- write to pipe, which blocks -- close pipe --- write to pipe -- (kernel generates SIGPIPE) -- --- There is a synchronization point at the open()s, but the child may --- still do the write before the parent closes its end of the pipe, --- causing the signal not to be delivered. To handle this, we need --- to introduce a second pipe to use as a semaphore: +-- There is a synchronization point at the open()s, but it is +-- essential to ensure that the child's write operation fills the +-- kernel's pipe buffer and blocks. If we did not fill the pipe +-- buffer, the write could complete and return before the parent +-- closes its end of the pipe, causing the signal not to be delivered. -- --- parent child --- ------ ----- --- fork --- exec --- open p1 for write --- open p1 for read --- open p2 for write --- close p1 --- open p2 for read --- write to p1 --- (kernel generates SIGPIPE) +-- Kernel pipe buffers are known to be as big as 64K. Thus, it is +-- overkill to make four commits each with an 64K log message, but I +-- like me some overkill. (There is a temptation to make it sixteen; +-- I can imagine someone deciding to bulk up the pipe buffer to a nice +-- round megabyte. But the time this test takes is proportional to +-- the number of commits, so I won't. I tried having a bigger log +-- message but that crashed "mtn commit".) -- --- It does not matter which side opens p2 for read and which for --- write, so we have each process open both pipes the same way. --- The code for the child half of this is in "hookfile". --- --- Note that if we ever get the ability to redirect stdout in bg(), --- then we should point it at p1, and have hookfile just synchronize --- with p2; this tests even more closely the case we care about. +-- The following 1024-byte block of nonsense is courtesy of the Eater +-- of Meaning. -check({"mkfifo", "fifo1"}, 0) -check({"mkfifo", "fifo2"}, 0) -check(get("hookfile")) +message = [[ +Won whip he keel, dens canal ply chafe hoots tooler gad nut pal hew +visa. Area dunn felts morrow exxon bib bern oz toil clot knightsbridge +malta tex organs. Respect, aft beehive, dip i mitchell walrus en BELY +Stow 5 pot juice 79 oberon preamble io Arabian, stag timers loy son +Paws fat i ram suez wiper, den ron unix minaret wire po fox sicilian +nubia puss fight. Oz sweeneys be mckee on paving eyers, em eel a +johnny thumbed illegal sash do ku 8,296 jazz, margo or rib ah fess +swine so vat up timeouts. Us drop fed hip beds ha i meaner (ax todays +suez of withdraw 53 electrify) dim en ah listings-cinnamon ad minded +Anu races nod abui a abide. -proc = bg(mtn("log", "--rcfile=hookfile"), -SIGPIPE, true, true) +Epaulet if brisker de carnivals mae ed civic lettering alfa ale pandas +(micaa pry ada zoo pale or opt Tax Shy Slowed incapable), wee hem +bernoulli ott ha harlem he malabar sir Roach cortex ash avouch as Soda +Jimi. Ohm thief ox bay loops shaves gobi nu pi reese-ax-roe-waging +vieti salable bin love soft all oz oboe plush sniffed rowdy em +asserting used en sit ham land nat fly. +]] -p1, e1 = io.open("fifo1", "r") -if p1 == nil then err(e1) end -p1:close() -p2, e2 = io.open("fifo2", "r") -if p2 == nil then err(e2) end -p2:close() +for i = 1,6 do + message = message .. message +end +mtn_setup() +addfile("file", "fnord") +for i = 1,4 do + writefile("file", "commit "..tonumber(i).."\n") + commit(nil, message) +end + +check({"mkfifo", "fifo"}, 0, nil, nil) + +-- We do this crazy thing because bg() can't redirect stdout. +-- FIXME: It should be able to redirect stdout. +-- FIXME: The quoting here will break if any of the strings +-- produced by mtn() contains a single quote. + +logcmd = "exec '" .. table.concat(mtn("log", "--no-graph"), "' '") .. "' >fifo" + +proc = bg({"/bin/sh", "-c", logcmd}, -SIGPIPE, nil, false) + +p, e = io.open("fifo", "r") +if p == nil then err(e) end +p:close() proc:finish(3) -- three second timeout