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

Re: [PATCH v2 12/16] diff: use tempfile module

From
Michael Haggerty <mhagger@alum.mit.edu>
Date
Aug 12, 2015, 15:13 UTC
Message-ID
<55CB62B7.8060706@alum.mit.edu>
In-Reply-To
<xmqqbnedr3sp.fsf@gitster.dls.corp.google.com>
On 08/11/2015 10:03 PM, Junio C Hamano wrote:
Show 51 quoted lines
> Michael Haggerty <mhagger@alum.mit.edu> writes:
> 
>> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
>> ---
>>  diff.c | 29 +++++++----------------------
>>  1 file changed, 7 insertions(+), 22 deletions(-)
> 
> Nice code reduction.
> 
>> diff --git a/diff.c b/diff.c
>> index 7500c55..dc95247 100644
>> --- a/diff.c
>> +++ b/diff.c
>> @@ -2,6 +2,7 @@
>>   * Copyright (C) 2005 Junio C Hamano
>>   */
>>  #include "cache.h"
>> +#include "tempfile.h"
>>  #include "quote.h"
>>  #include "diff.h"
>>  #include "diffcore.h"
>> @@ -312,7 +313,7 @@ static struct diff_tempfile {
>>  	const char *name; /* filename external diff should read from */
>>  	char hex[41];
>>  	char mode[10];
>> -	char tmp_path[PATH_MAX];
>> +	struct tempfile tempfile;
>>  } diff_temp[2];
>>  
>>  typedef unsigned long (*sane_truncate_fn)(char *line, unsigned long len);
>> @@ -564,25 +565,16 @@ static struct diff_tempfile *claim_diff_tempfile(void) {
>>  	die("BUG: diff is failing to clean up its tempfiles");
>>  }
>>  
>> -static int remove_tempfile_installed;
>> -
>>  static void remove_tempfile(void)
>>  {
>>  	int i;
>>  	for (i = 0; i < ARRAY_SIZE(diff_temp); i++) {
>> -		if (diff_temp[i].name == diff_temp[i].tmp_path)
>> -			unlink_or_warn(diff_temp[i].name);
>> +		if (is_tempfile_active(&diff_temp[i].tempfile))
>> +			delete_tempfile(&diff_temp[i].tempfile);
> 
> I suspect that this indicates that there is something iffy in the
> conversion.  The original invariant, that is consistently used
> between claim_diff_tempfile() and remove_tempfile(), is that .name
> field points at .tmp_path for a slot in diff_temp[] that holds a
> temporary that is in use.  Otherwise, .name is NULL and it can be
> claimed for your own use.

No, prepare_temp_file() sometimes sets diff_tempfile::name to "/dev/null", and sometimes to point at its argument `name`. In either of these cases .tmp_path can hold anything, and the file is *not* cleaned up even though the diff_temp entry is considered by claim_diff_tempfile() to be in use.

If I'm not mistaken, the old invariant was:
* Iff diff_tempfile::name is NULL, the entry is not in use.
* Iff diff_tempfile::name == diff_tempfile::tmp_path, then the entry is
in use and refers to a temporary file that needs to be cleaned up.
* Otherwise, the entry is in use but the corresponding file should *not*
be cleaned up.
The new invariant is:
* Iff diff_tempfile::name is NULL, the entry is not in use. In these
cases, is_tempfile_active() is always false.
* Iff is_tempfile_active(diff_tempfile::tempfile), then it refers to a
file that needs to get cleaned up. In these cases name points at the
tempfile object's filename.
* If neither of the above is true, then the entry is in use but the
corresponding file should not be cleaned up.
> Here the updated code uses a different and new invariant: .tempfile
> satisfies is_tempfile_active() for a slot in use.  But the check in
> claim_diff_tempfile() still relies on the original invariant.

That is not true. The is_tempfile_active() check is only used in remove_tempfile() when deciding whether to clean up the file. The check in claim_diff_tempfile() wants to know whether the entry is in use, so it uses the other check.

Show 10 quoted lines
> The updated code may happen to always have an active tempfile in
> tempfile and always set NULL when it clears .name, but that would
> mean (1) future changes may easily violate one of invariants (we
> used to have only one, now we have two that have to be sync) by
> mistake, and (2) we are keeping track of two closely linked things
> as two invariants.
> 
> As the value that used to be in the .name field can now be obtained
> by calling get_tempfile_path() on the .tempfile field, perhaps we
> should drop .name (and its associated invariant) at the same time?
This is also incorrect. See my first paragraph above.
I will change this patch to document the invariants.
Michael
-- 
Michael Haggerty
mhagger@alum.mit.edu
Previous: Junio C HamanoNext: Junio C Hamano
Message 19 of 29 in “Introduce a tempfile module”
  1. 00/16 Introduce a tempfile moduleMichael Haggerty, Aug 10, 2015
  2. 01/16 Move lockfile documentation to lockfile.h and lockfile.cMichael Haggerty, Aug 10, 2015
  3. Junio C HamanoAug 11, 2015
  4. 02/16 create_bundle(): duplicate file descriptor to avoid closing it twiceMichael Haggerty, Aug 10, 2015
  5. 03/16 lockfile: add accessors get_lock_file_fd() and get_lock_file_fp()Michael Haggerty, Aug 10, 2015
  6. Junio C HamanoAug 11, 2015
  7. 04/16 lockfile: add accessor get_lock_file_path()Michael Haggerty, Aug 10, 2015
  8. Junio C HamanoAug 11, 2015
  9. 05/16 commit_lock_file(): use get_locked_file_path()Michael Haggerty, Aug 10, 2015
  10. 06/16 tempfile: a new module for handling temporary filesMichael Haggerty, Aug 10, 2015
  11. 07/16 prepare_tempfile_object(): new function, extracted from create_tempfile()Michael Haggerty, Aug 10, 2015
  12. Junio C HamanoAug 11, 2015
  13. 08/16 tempfile: add several functions for creating temporary filesMichael Haggerty, Aug 10, 2015
  14. 09/16 register_tempfile(): new function to handle an existing temporary fileMichael Haggerty, Aug 10, 2015
  15. 10/16 write_shared_index(): use tempfile moduleMichael Haggerty, Aug 10, 2015
  16. 11/16 setup_temporary_shallow(): use tempfile moduleMichael Haggerty, Aug 10, 2015
  17. 12/16 diff: use tempfile moduleMichael Haggerty, Aug 10, 2015
  18. Junio C HamanoAug 11, 2015
  19. Michael HaggertyAug 12, 2015
  20. Junio C HamanoAug 12, 2015
  21. 12/16 diff: use tempfile moduleMichael Haggerty, Aug 12, 2015
  22. 13/16 lock_repo_for_gc(): compute the path to "gc.pid" only onceMichael Haggerty, Aug 10, 2015
  23. Junio C HamanoAug 11, 2015
  24. Junio C HamanoAug 11, 2015
  25. 14/16 gc: use tempfile module to handle gc.pid fileMichael Haggerty, Aug 10, 2015
  26. 15/16 credential-cache--daemon: delete socket from main()Michael Haggerty, Aug 10, 2015
  27. 16/16 credential-cache--daemon: use tempfile moduleMichael Haggerty, Aug 10, 2015
  28. Junio C HamanoAug 11, 2015
  29. Michael HaggertyAug 12, 2015

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.