git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v3 10/10] convert: add filter.<driver>.process option

From
Jakub Narębski <jnareb@gmail.com>
Date
Aug 4, 2016, 10:18 UTC
Message-ID
<0b7d7d96-dfdc-54a4-2c24-2aead6743ae1@gmail.com>
In-Reply-To
<9DDA993E-2AFD-4C69-8E22-58601EEC8A40@gmail.com>
[Some of this answer might have been invalidated by v4;
 I might be away from computer for a few days, so I won't be reviewing]
W dniu 03.08.2016 o 15:10, Lars Schneider pisze:
> On 01 Aug 2016, at 00:19, Jakub Narębski <jnareb@gmail.com> wrote:
>> W dniu 30.07.2016 o 01:38, larsxschneider@gmail.com pisze:
[...]
 
Show 6 quoted lines
>> Could this whole "send single file" be put in a separate function?
>> Or is it not worth it?
> 
> This function would have almost the same signature as apply_protocol2_filter
> and therefore I would say it's not worth it since the function is not
> crazy long.
 
All right.  Though I would say that if it makes the function more
readable, then it might be worth it.
[...]
Show 8 quoted lines
>>> +
>>> +	sigchain_push(SIGPIPE, SIG_IGN);
>>
>> Hmmm... ignoring SIGPIPE was good for one-shot filters.  Is it still
>> O.K. for per-command persistent ones?
> 
> Very good question. You are right... we don't want to ignore any errors
> during the protocol... I will remove it.
I was actually just wondering.

Actually the default behavior if SIGPIPE is not ignored (or if the SIGPIPE signal is not blocked / masked out) is to *terminate* the writing program, which we do not want.

The correct solution is to check for error during write, and check if errno is set to EPIPE. This means that reader (filter driver process) has closed pipe, usually due to crash, and we need to handle that sanely, either restarting or quitting while providing sane information about error to the user.

Well, we might want to set a signal handler for SIGPIPE, not just simply ignore it (especially for streaming case; stop streaming if filter driver crashed); though signal handlers are quite limited about what might be done in them. But that's for the future.

Read from closed pipe returns EOF; write to closed pipe results in
SIGPIPE and returns -1 (setting errno to EPIPE).
 
Show 19 quoted lines
>>
>>> +
>>> +	packet_buf_write(&nbuf, "%s\n", filter_type);
>>> +	ret &= !direct_packet_write(process->in, nbuf.buf, nbuf.len, 1);
>>> +
>>> +	if (ret) {
>>> +		strbuf_reset(&nbuf);
>>> +		packet_buf_write(&nbuf, "filename=%s\n", path);
>>> +		ret = !direct_packet_write(process->in, nbuf.buf, nbuf.len, 1);
>>> +	}
>>
>> Perhaps a better solution would be
>>
>>        if (err)
>>        	goto fin_error;
>>
>> rather than this.
> 
> OK, I change it to goto error handling style.
Well, at least try it and check if it makes code more readable.
 
Show 11 quoted lines
>>> +	if (ret) {
>>> +		strbuf_reset(&nbuf);
>>> +		packet_buf_write(&nbuf, "size=%"PRIuMAX"\n", (uintmax_t)len);
>>> +		ret = !direct_packet_write(process->in, nbuf.buf, nbuf.len, 1);
>>> +	}
>>
>> Or maybe extract writing the header for a file into a separate function?
>> This one gets a bit long...
> 
> Maybe... but I think that would make it harder to understand the protocol. I
> think I would prefer to have all the communication in one function layer.

I don't understand your reasoning here ("make it harder to understand the protocol"). If you choose good names for function writing header, then the main function would be the high-level view of protocol, e.g.

   git> <command>
   git> <header>
   git> <contents>
   git> <flush>
   git< <command accepted>
   git< <contents>
   git< <flush>
   git< <sent status>
 
[...]
Show 13 quoted lines
>>> +
>>> +	if (ret) {
>>> +		filter_result = packet_read_line(process->out, NULL);
>>> +		ret = !strcmp(filter_result, "success");
>>> +	}
>>> +
>>> +	sigchain_pop(SIGPIPE);
>>> +
>>> +	if (ret) {
>>> +		strbuf_swap(dst, &nbuf);
>>> +	} else {
>>> +		if (!filter_result || strcmp(filter_result, "reject")) {
>>> +			// Something went wrong with the protocol filter. Force shutdown!
Don't use C++ one-line comments (that's C99-ism).
Show 16 quoted lines
>>> +			error("external filter '%s' failed", cmd);
>>> +			kill_protocol2_filter(&cmd_process_map, entry);
>>> +		}
>>> +	}
>>
>> So if Git gets finish signal "success" from filter, it accepts the output.
>> If Git gets finish signal "reject" from filter, it restarts filter (and
>> reject the output - user can retry the command himself / herself).
>> If Git gets any other finish signal, for example "error" (but this is not
>> standarized), then it rejects the output, keeping the unfiltered result,
>> but keeps filtering.
>>
>> I think it is not described in this detail in the documentation of the
>> new protocol.
> 
> Agreed, will add!
That would be nice.
Show 16 quoted lines
>>> -	return apply_filter(path, NULL, 0, -1, NULL, ca.drv->clean);
>>> +	if (!ca.drv->clean && ca.drv->process)
>>> +		return apply_protocol2_filter(
>>> +			path, NULL, 0, -1, NULL, ca.drv->process, FILTER_CAPABILITIES_CLEAN
>>> +		);
>>> +	else
>>> +		return apply_filter(path, NULL, 0, -1, NULL, ca.drv->clean);
>>
>> Could we augment apply_filter() instead, so that the invocation is
>>
>>        return apply_filter(path, NULL, 0, -1, NULL, ca.drv, FILTER_CLEAN);
>>
>> Though I am not sure if moving this conditional to apply_filter would
>> be a good idea; maybe wrapper around augmented apply_filter_do()?
> 
> Yes, a wrapper makes it way cleaner!

That's good, because we have quite a few of those constructs. And I think the compiler would inline it, so there is no penalty.

>>> diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
[...]
Show 8 quoted lines
>>> +		git branch empty &&
>>> +
>>> +		cat ../test.o >test.r &&
>>
>> Err, the above is just copying file, isn't it?
>> Maybe it was copied from other tests, I have not checked.
> 
> It was created in the "setup" test.
 
What I meant here (among other things) is that you uselessly use
'cat' to copy files:
    +		cp ../test.o test.r &&
 
Show 10 quoted lines
>>> +		echo "test22" >test2.r &&
>>> +		mkdir testsubdir &&
>>> +		echo "test333" >testsubdir/test3.r &&
>>
>> All right, we test text file, we test binary file (I assume), we test
>> file in a subdirectory.  What about testing empty file?  Or large file
>> which would not fit in the stdin/stdout buffer (as EXPENSIVE test)?
> 
> No binary file. The main reason for this test is to check multiple files.
> I'll add a empty file. A large file is tested in the next test.

I assume that this large file is binary file; what matters is that it includes NUL character ("\0"), i.e. zero byte, checking that there is no error that would terminate it at NUL.

I'll end here for now.
-- 
Jakub Narębski
Previous: Lars SchneiderNext: Lars Schneider
Message 48 of 100 in “Git filter protocol”
  1. 00/10 Git filter protocollarsxschneider@gmail.com, Jul 29, 2016
  2. 01/10 pkt-line: extract set_packet_header()larsxschneider@gmail.com, Jul 29, 2016
  3. Jakub NarębskiJul 30, 2016
  4. Lars SchneiderAug 1, 2016
  5. Jakub NarębskiAug 3, 2016
  6. Lars SchneiderAug 5, 2016
  7. 02/10 pkt-line: add direct_packet_write() and direct_packet_write_data()larsxschneider@gmail.com, Jul 29, 2016
  8. Jakub NarębskiJul 30, 2016
  9. Lars SchneiderAug 1, 2016
  10. Jakub NarębskiAug 3, 2016
  11. Lars SchneiderAug 5, 2016
  12. 03/10 pkt-line: add packet_flush_gentle()larsxschneider@gmail.com, Jul 29, 2016
  13. Jakub NarębskiJul 30, 2016
  14. Lars SchneiderAug 1, 2016
  15. Torstem BögershausenJul 31, 2016
  16. Lars SchneiderJul 31, 2016
  17. Torsten BögershausenAug 2, 2016
  18. Lars SchneiderAug 5, 2016
  19. 04/10 pkt-line: call packet_trace() only if a packet is actually sendlarsxschneider@gmail.com, Jul 29, 2016
  20. Jakub NarębskiJul 30, 2016
  21. Lars SchneiderAug 1, 2016
  22. Jakub NarębskiAug 3, 2016
  23. 05/10 pack-protocol: fix maximum pkt-line sizelarsxschneider@gmail.com, Jul 29, 2016
  24. Jakub NarębskiJul 30, 2016
  25. Lars SchneiderAug 1, 2016
  26. 07/10 convert: quote filter names in error messageslarsxschneider@gmail.com, Jul 29, 2016
  27. 06/10 run-command: add clean_on_exit_handlerlarsxschneider@gmail.com, Jul 29, 2016
  28. Johannes SixtJul 30, 2016
  29. Lars SchneiderAug 1, 2016
  30. Johannes SixtAug 2, 2016
  31. Lars SchneiderAug 2, 2016
  32. 08/10 convert: modernize testslarsxschneider@gmail.com, Jul 29, 2016
  33. 09/10 convert: generate large test files only oncelarsxschneider@gmail.com, Jul 29, 2016
  34. 10/10 convert: add filter.<driver>.process optionlarsxschneider@gmail.com, Jul 29, 2016
  35. Jakub NarębskiJul 30, 2016
  36. Jakub NarębskiJul 31, 2016
  37. Lars SchneiderJul 31, 2016
  38. Jakub NarębskiJul 31, 2016
  39. Lars SchneiderAug 1, 2016
  40. Designing the filter process protocol (was: Re: [PATCH v3 10/10] convert: add filter.<driver>.process option)Jakub Narębski, Aug 3, 2016
  41. Lars SchneiderAug 5, 2016
  42. Lars SchneiderAug 6, 2016
  43. Jakub NarębskiAug 3, 2016
  44. Jakub NarębskiJul 31, 2016
  45. Lars SchneiderAug 1, 2016
  46. Jakub NarębskiAug 4, 2016
  47. Lars SchneiderAug 3, 2016
  48. Jakub NarębskiAug 4, 2016
  49. Lars SchneiderAug 5, 2016
  50. 00/12 Git filter protocollarsxschneider@gmail.com, Aug 3, 2016
  51. 01/12 pkt-line: extract set_packet_header()larsxschneider@gmail.com, Aug 3, 2016
  52. Junio C HamanoAug 3, 2016
  53. Jeff KingAug 3, 2016
  54. Jeff KingAug 3, 2016
  55. Junio C HamanoAug 4, 2016
  56. Lars SchneiderAug 5, 2016
  57. Junio C HamanoAug 5, 2016
  58. Lars SchneiderAug 5, 2016
  59. Junio C HamanoAug 5, 2016
  60. Lars SchneiderAug 3, 2016
  61. 07/12 run-command: add clean_on_exit_handlerlarsxschneider@gmail.com, Aug 3, 2016
  62. Jeff KingAug 3, 2016
  63. Lars SchneiderAug 3, 2016
  64. Jeff KingAug 3, 2016
  65. Lars SchneiderAug 3, 2016
  66. Jeff KingAug 3, 2016
  67. Lars SchneiderAug 5, 2016
  68. Torsten BögershausenAug 5, 2016
  69. Lars SchneiderAug 5, 2016
  70. 03/12 pkt-line: add packet_flush_gentle()larsxschneider@gmail.com, Aug 3, 2016
  71. Jeff KingAug 3, 2016
  72. Junio C HamanoAug 4, 2016
  73. 02/12 pkt-line: add direct_packet_write() and direct_packet_write_data()larsxschneider@gmail.com, Aug 3, 2016
  74. 08/12 convert: quote filter names in error messageslarsxschneider@gmail.com, Aug 3, 2016
  75. 05/12 pkt-line: add functions to read/write flush terminated packet streamslarsxschneider@gmail.com, Aug 3, 2016
  76. 09/12 convert: modernize testslarsxschneider@gmail.com, Aug 3, 2016
  77. 12/12 convert: add filter.<driver>.process shutdown command optionlarsxschneider@gmail.com, Aug 3, 2016
  78. 06/12 pack-protocol: fix maximum pkt-line sizelarsxschneider@gmail.com, Aug 3, 2016
  79. 04/12 pkt-line: call packet_trace() only if a packet is actually sendlarsxschneider@gmail.com, Aug 3, 2016
  80. 11/12 convert: add filter.<driver>.process optionlarsxschneider@gmail.com, Aug 3, 2016
  81. Junio C HamanoAug 3, 2016
  82. Lars SchneiderAug 3, 2016
  83. Jeff KingAug 3, 2016
  84. Lars SchneiderAug 5, 2016
  85. Junio C HamanoAug 3, 2016
  86. Lars SchneiderAug 3, 2016
  87. Junio C HamanoAug 3, 2016
  88. Lars SchneiderAug 3, 2016
  89. Torsten BögershausenAug 5, 2016
  90. Lars SchneiderAug 5, 2016
  91. Junio C HamanoAug 5, 2016
  92. Jeff KingAug 5, 2016
  93. Lars SchneiderAug 6, 2016
  94. Jeff KingAug 6, 2016
  95. Lars SchneiderAug 6, 2016
  96. Jeff KingAug 8, 2016
  97. Lars SchneiderAug 8, 2016
  98. Jeff KingAug 8, 2016
  99. Torsten BögershausenAug 6, 2016
  100. 10/12 convert: generate large test files only oncelarsxschneider@gmail.com, Aug 3, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.