* config.c fixes @ 2007-12-14 19:22 Kristian Høgsberg 2007-12-14 19:22 ` [PATCH 1/2] Fix config lockfile handling Kristian Høgsberg 0 siblings, 1 reply; 8+ messages in thread From: Kristian Høgsberg @ 2007-12-14 19:22 UTC (permalink / raw) To: gitster; +Cc: git Hi, While strace'ing builtin-clone I saw this horror: ... write(3, "remote", 6) = 6 write(3, " = ", 3) = 3 write(3, "o", 1) = 1 write(3, "r", 1) = 1 write(3, "i", 1) = 1 write(3, "g", 1) = 1 write(3, "i", 1) = 1 write(3, "n", 1) = 1 write(3, "\n", 1) = 1 munmap(0xb7f72000, 102) = 0 close(3) = 0 close(3) = -1 EBADF (Bad file descriptor) ... That's just terrible. And hey, it turns out the code is terrible too. I think the best solution is to just parse up the entire config file up front and keep it in a data structure, make the changes and then write it all out at the end. That makes it cheap to make a series of changes too: config = open_config(file); set_key(config, key1, value1); set_key(config, key2, value2); set_key(config, key3, value3); commit_config(config); Or something. Anyway, for 1.5.4 I wrote the following two patches that fixes the 1-bytes writes and the double close. config.c | 113 +++++++++++++++++++++++-------------------------------------- 1 files changed, 43 insertions(+), 70 deletions(-) cheers, Kristian ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] Fix config lockfile handling. 2007-12-14 19:22 config.c fixes Kristian Høgsberg @ 2007-12-14 19:22 ` Kristian Høgsberg 2007-12-14 19:22 ` [PATCH 2/2] Use a strbuf for building up section header and key/value pair strings Kristian Høgsberg ` (2 more replies) 0 siblings, 3 replies; 8+ messages in thread From: Kristian Høgsberg @ 2007-12-14 19:22 UTC (permalink / raw) To: gitster; +Cc: git, Kristian Høgsberg When we commit or roll back the lock file the fd is automatically closed, so don't do that again. Also, just keep the lock on the stack. Signed-off-by: Kristian Høgsberg <krh@redhat.com> --- config.c | 22 +++++----------------- 1 files changed, 5 insertions(+), 17 deletions(-) diff --git a/config.c b/config.c index 49d2b42..0725563 100644 --- a/config.c +++ b/config.c @@ -754,7 +754,7 @@ int git_config_set_multivar(const char* key, const char* value, int fd = -1, in_fd; int ret; char* config_filename; - struct lock_file *lock = NULL; + struct lock_file lock; const char* last_dot = strrchr(key, '.'); config_filename = getenv(CONFIG_ENVIRONMENT); @@ -811,8 +811,7 @@ int git_config_set_multivar(const char* key, const char* value, * The lock serves a purpose in addition to locking: the new * contents of .git/config will be written into it. */ - lock = xcalloc(sizeof(struct lock_file), 1); - fd = hold_lock_file_for_update(lock, config_filename, 0); + fd = hold_lock_file_for_update(&lock, config_filename, 0); if (fd < 0) { fprintf(stderr, "could not lock config file\n"); free(store.key); @@ -955,28 +954,17 @@ int git_config_set_multivar(const char* key, const char* value, munmap(contents, contents_sz); } - if (close(fd) || commit_lock_file(lock) < 0) { + if (commit_lock_file(&lock) < 0) { fprintf(stderr, "Cannot commit config file!\n"); ret = 4; goto out_free; } - /* fd is closed, so don't try to close it below. */ - fd = -1; - /* - * lock is committed, so don't try to roll it back below. - * NOTE: Since lockfile.c keeps a linked list of all created - * lock_file structures, it isn't safe to free(lock). It's - * better to just leave it hanging around. - */ - lock = NULL; ret = 0; out_free: - if (0 <= fd) - close(fd); - if (lock) - rollback_lock_file(lock); + /* If we already committed the lock file, the rollback is a no-op. */ + rollback_lock_file(&lock); free(config_filename); return ret; -- 1.5.3.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] Use a strbuf for building up section header and key/value pair strings. 2007-12-14 19:22 ` [PATCH 1/2] Fix config lockfile handling Kristian Høgsberg @ 2007-12-14 19:22 ` Kristian Høgsberg 2007-12-14 19:29 ` [PATCH 1/2] Fix config lockfile handling Johannes Schindelin 2007-12-14 19:32 ` Johannes Sixt 2 siblings, 0 replies; 8+ messages in thread From: Kristian Høgsberg @ 2007-12-14 19:22 UTC (permalink / raw) To: gitster; +Cc: git, Kristian Høgsberg Avoids horrible 1-byte write(2) calls and cleans up the logic a bit. Signed-off-by: Kristian Høgsberg <krh@redhat.com> --- config.c | 91 ++++++++++++++++++++++++++------------------------------------ 1 files changed, 38 insertions(+), 53 deletions(-) diff --git a/config.c b/config.c index 0725563..3392bc4 100644 --- a/config.c +++ b/config.c @@ -610,46 +610,36 @@ static int write_error(void) static int store_write_section(int fd, const char* key) { - const char *dot = strchr(key, '.'); - int len1 = store.baselen, len2 = -1; + const char *dot; + int i, success; + struct strbuf sb; - dot = strchr(key, '.'); + strbuf_init(&sb, 0); + dot = memchr(key, '.', store.baselen); if (dot) { - int dotlen = dot - key; - if (dotlen < len1) { - len2 = len1 - dotlen - 1; - len1 = dotlen; + strbuf_addf(&sb, "[%.*s \"", dot - key, key); + for (i = dot - key + 1; i < store.baselen; i++) { + if (key[i] == '"') + strbuf_addch(&sb, '\\'); + strbuf_addch(&sb, key[i]); } + strbuf_addstr(&sb, "\"]\n"); + } else { + strbuf_addf(&sb, "[%.*s]\n", store.baselen, key); } - if (write_in_full(fd, "[", 1) != 1 || - write_in_full(fd, key, len1) != len1) - return 0; - if (len2 >= 0) { - if (write_in_full(fd, " \"", 2) != 2) - return 0; - while (--len2 >= 0) { - unsigned char c = *++dot; - if (c == '"') - if (write_in_full(fd, "\\", 1) != 1) - return 0; - if (write_in_full(fd, &c, 1) != 1) - return 0; - } - if (write_in_full(fd, "\"", 1) != 1) - return 0; - } - if (write_in_full(fd, "]\n", 2) != 2) - return 0; + success = write_in_full(fd, sb.buf, sb.len) == sb.len; + strbuf_release(&sb); - return 1; + return success; } static int store_write_pair(int fd, const char* key, const char* value) { - int i; - int length = strlen(key+store.baselen+1); - int quote = 0; + int i, success; + int length = strlen(key + store.baselen + 1); + const char *quote = ""; + struct strbuf sb; /* * Check to see if the value needs to be surrounded with a dq pair. @@ -659,43 +649,38 @@ static int store_write_pair(int fd, const char* key, const char* value) * configuration parser. */ if (value[0] == ' ') - quote = 1; + quote = "\""; for (i = 0; value[i]; i++) if (value[i] == ';' || value[i] == '#') - quote = 1; - if (i && value[i-1] == ' ') - quote = 1; + quote = "\""; + if (i && value[i - 1] == ' ') + quote = "\""; + + strbuf_init(&sb, 0); + strbuf_addf(&sb, "\t%.*s = %s", + length, key + store.baselen + 1, quote); - if (write_in_full(fd, "\t", 1) != 1 || - write_in_full(fd, key+store.baselen+1, length) != length || - write_in_full(fd, " = ", 3) != 3) - return 0; - if (quote && write_in_full(fd, "\"", 1) != 1) - return 0; for (i = 0; value[i]; i++) switch (value[i]) { case '\n': - if (write_in_full(fd, "\\n", 2) != 2) - return 0; + strbuf_addstr(&sb, "\\n"); break; case '\t': - if (write_in_full(fd, "\\t", 2) != 2) - return 0; + strbuf_addstr(&sb, "\\t"); break; case '"': case '\\': - if (write_in_full(fd, "\\", 1) != 1) - return 0; + strbuf_addch(&sb, '\\'); default: - if (write_in_full(fd, value+i, 1) != 1) - return 0; + strbuf_addch(&sb, value[i]); break; } - if (quote && write_in_full(fd, "\"", 1) != 1) - return 0; - if (write_in_full(fd, "\n", 1) != 1) - return 0; - return 1; + strbuf_addf(&sb, "%s\n", quote); + + success = write_in_full(fd, sb.buf, sb.len) == sb.len; + strbuf_release(&sb); + + return success; } static ssize_t find_beginning_of_line(const char* contents, size_t size, -- 1.5.3.4 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] Fix config lockfile handling. 2007-12-14 19:22 ` [PATCH 1/2] Fix config lockfile handling Kristian Høgsberg 2007-12-14 19:22 ` [PATCH 2/2] Use a strbuf for building up section header and key/value pair strings Kristian Høgsberg @ 2007-12-14 19:29 ` Johannes Schindelin 2007-12-14 20:07 ` Junio C Hamano 2007-12-14 19:32 ` Johannes Sixt 2 siblings, 1 reply; 8+ messages in thread From: Johannes Schindelin @ 2007-12-14 19:29 UTC (permalink / raw) To: Kristian Høgsberg; +Cc: gitster, git [-- Attachment #1: Type: TEXT/PLAIN, Size: 240 bytes --] Hi, On Fri, 14 Dec 2007, Kristian Høgsberg wrote: > - struct lock_file *lock = NULL; > + struct lock_file lock; AFAICT this cannot work. At least not reliably. An atexit() handler will access all (even closed) lockfiles. Ciao, Dscho ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] Fix config lockfile handling. 2007-12-14 19:29 ` [PATCH 1/2] Fix config lockfile handling Johannes Schindelin @ 2007-12-14 20:07 ` Junio C Hamano 2007-12-14 20:15 ` Johannes Schindelin 0 siblings, 1 reply; 8+ messages in thread From: Junio C Hamano @ 2007-12-14 20:07 UTC (permalink / raw) To: Johannes Schindelin; +Cc: Kristian Høgsberg, gitster, git Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: > Hi, > > On Fri, 14 Dec 2007, Kristian Høgsberg wrote: > >> - struct lock_file *lock = NULL; >> + struct lock_file lock; > > AFAICT this cannot work. At least not reliably. An atexit() handler will > access all (even closed) lockfiles. Correct. It cannot be on the stack. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] Fix config lockfile handling. 2007-12-14 20:07 ` Junio C Hamano @ 2007-12-14 20:15 ` Johannes Schindelin 2007-12-14 21:18 ` Junio C Hamano 0 siblings, 1 reply; 8+ messages in thread From: Johannes Schindelin @ 2007-12-14 20:15 UTC (permalink / raw) To: Junio C Hamano; +Cc: Kristian Høgsberg, git [-- Attachment #1: Type: TEXT/PLAIN, Size: 481 bytes --] Hi, On Fri, 14 Dec 2007, Junio C Hamano wrote: > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: > > > On Fri, 14 Dec 2007, Kristian Høgsberg wrote: > > > >> - struct lock_file *lock = NULL; > >> + struct lock_file lock; > > > > AFAICT this cannot work. At least not reliably. An atexit() handler > > will access all (even closed) lockfiles. > > Correct. It cannot be on the stack. Note that this behaviour will be another obstacle to libification. Ciao, Dscho ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] Fix config lockfile handling. 2007-12-14 20:15 ` Johannes Schindelin @ 2007-12-14 21:18 ` Junio C Hamano 0 siblings, 0 replies; 8+ messages in thread From: Junio C Hamano @ 2007-12-14 21:18 UTC (permalink / raw) To: Johannes Schindelin; +Cc: Kristian Høgsberg, git Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: >> > AFAICT this cannot work. At least not reliably. An atexit() handler >> > will access all (even closed) lockfiles. >> >> Correct. It cannot be on the stack. > > Note that this behaviour will be another obstacle to libification. By your definition of "obstacle", there is no work at all in libification if the system is obstacle free. Libification is all about removing run-once-and-exit and atexit() is just a part of it. I think we can do this step-by-step by first introducing a new function "get_lockfile()" that takes a list of active lockfiles (perhaps that would be a part of "client context" thing in the library) and gives back a lockfile structure allocated on heap, registers it to the list of lockfiles that need to be eventually cleaned up, and another function "rollback_lockfiles()" that take the list of lockfiles in the "client context" and rolls them all back. Once there is such a "client contex", in the current unlibified "main" routines can then declare a global client context, obtain and use lockfiles for that context, and directly call rollback_lockfiles() from the atexit() handler. But that is all post 1.5.4. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] Fix config lockfile handling. 2007-12-14 19:22 ` [PATCH 1/2] Fix config lockfile handling Kristian Høgsberg 2007-12-14 19:22 ` [PATCH 2/2] Use a strbuf for building up section header and key/value pair strings Kristian Høgsberg 2007-12-14 19:29 ` [PATCH 1/2] Fix config lockfile handling Johannes Schindelin @ 2007-12-14 19:32 ` Johannes Sixt 2 siblings, 0 replies; 8+ messages in thread From: Johannes Sixt @ 2007-12-14 19:32 UTC (permalink / raw) To: Kristian Høgsberg, git, gitster Kristian Høgsberg wrote: > When we commit or roll back the lock file the fd is automatically closed, > so don't do that again. Also, just keep the lock on the stack. IIRC, locks are accessed from atexit(), e.g. during a die(). So you must not put one on the stack. -- Hannes ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2007-12-14 21:19 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-12-14 19:22 config.c fixes Kristian Høgsberg 2007-12-14 19:22 ` [PATCH 1/2] Fix config lockfile handling Kristian Høgsberg 2007-12-14 19:22 ` [PATCH 2/2] Use a strbuf for building up section header and key/value pair strings Kristian Høgsberg 2007-12-14 19:29 ` [PATCH 1/2] Fix config lockfile handling Johannes Schindelin 2007-12-14 20:07 ` Junio C Hamano 2007-12-14 20:15 ` Johannes Schindelin 2007-12-14 21:18 ` Junio C Hamano 2007-12-14 19:32 ` Johannes Sixt
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).