rugged 0.23.3 → 0.24.0b0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/ext/rugged/rugged.c +24 -0
- data/ext/rugged/rugged_config.c +65 -0
- data/ext/rugged/rugged_remote.c +22 -2
- data/ext/rugged/rugged_repo.c +10 -5
- data/ext/rugged/rugged_tree.c +4 -1
- data/lib/rugged/version.rb +1 -1
- data/vendor/libgit2/CMakeLists.txt +47 -2
- data/vendor/libgit2/include/git2/config.h +18 -0
- data/vendor/libgit2/include/git2/diff.h +25 -2
- data/vendor/libgit2/include/git2/errors.h +0 -12
- data/vendor/libgit2/include/git2/index.h +11 -0
- data/vendor/libgit2/include/git2/remote.h +12 -1
- data/vendor/libgit2/include/git2/sys/config.h +14 -0
- data/vendor/libgit2/include/git2/sys/filter.h +4 -1
- data/vendor/libgit2/include/git2/sys/odb_backend.h +4 -0
- data/vendor/libgit2/include/git2/sys/refdb_backend.h +5 -4
- data/vendor/libgit2/include/git2/sys/transport.h +27 -0
- data/vendor/libgit2/include/git2/transport.h +25 -21
- data/vendor/libgit2/include/git2/version.h +2 -2
- data/vendor/libgit2/libgit2.pc.in +3 -2
- data/vendor/libgit2/src/branch.c +1 -12
- data/vendor/libgit2/src/checkout.c +29 -20
- data/vendor/libgit2/src/clone.c +2 -2
- data/vendor/libgit2/src/common.h +13 -4
- data/vendor/libgit2/src/config.c +36 -0
- data/vendor/libgit2/src/config.h +15 -0
- data/vendor/libgit2/src/config_file.c +124 -20
- data/vendor/libgit2/src/config_file.h +10 -0
- data/vendor/libgit2/src/curl_stream.c +7 -7
- data/vendor/libgit2/src/diff.c +89 -27
- data/vendor/libgit2/src/diff_print.c +1 -1
- data/vendor/libgit2/src/errors.c +75 -40
- data/vendor/libgit2/src/filebuf.c +81 -3
- data/vendor/libgit2/src/fileops.c +176 -75
- data/vendor/libgit2/src/fileops.h +7 -10
- data/vendor/libgit2/src/filter.c +5 -2
- data/vendor/libgit2/src/global.c +25 -9
- data/vendor/libgit2/src/global.h +1 -0
- data/vendor/libgit2/src/idxmap.h +92 -0
- data/vendor/libgit2/src/ignore.c +9 -7
- data/vendor/libgit2/src/index.c +246 -46
- data/vendor/libgit2/src/index.h +2 -0
- data/vendor/libgit2/src/iterator.c +377 -118
- data/vendor/libgit2/src/iterator.h +28 -20
- data/vendor/libgit2/src/merge.c +26 -13
- data/vendor/libgit2/src/notes.c +1 -1
- data/vendor/libgit2/src/odb.c +1 -2
- data/vendor/libgit2/src/odb_loose.c +2 -2
- data/vendor/libgit2/src/odb_mempack.c +6 -2
- data/vendor/libgit2/src/oidmap.h +2 -0
- data/vendor/libgit2/src/openssl_stream.c +9 -3
- data/vendor/libgit2/src/path.c +37 -2
- data/vendor/libgit2/src/path.h +12 -1
- data/vendor/libgit2/src/pathspec.c +12 -12
- data/vendor/libgit2/src/push.c +2 -1
- data/vendor/libgit2/src/push.h +1 -0
- data/vendor/libgit2/src/refdb.c +2 -6
- data/vendor/libgit2/src/refdb_fs.c +13 -3
- data/vendor/libgit2/src/remote.c +44 -15
- data/vendor/libgit2/src/repository.c +28 -12
- data/vendor/libgit2/src/stash.c +17 -12
- data/vendor/libgit2/src/stransport_stream.c +1 -1
- data/vendor/libgit2/src/submodule.c +234 -152
- data/vendor/libgit2/src/sysdir.c +22 -8
- data/vendor/libgit2/src/transaction.c +41 -0
- data/vendor/libgit2/src/transaction.h +14 -0
- data/vendor/libgit2/src/transports/cred.c +8 -0
- data/vendor/libgit2/src/transports/http.c +6 -0
- data/vendor/libgit2/src/transports/smart.c +95 -0
- data/vendor/libgit2/src/transports/smart.h +1 -0
- data/vendor/libgit2/src/transports/smart_pkt.c +9 -2
- data/vendor/libgit2/src/transports/ssh.c +5 -3
- data/vendor/libgit2/src/transports/winhttp.c +19 -1
- data/vendor/libgit2/src/unix/posix.h +14 -1
- data/vendor/libgit2/src/util.c +56 -13
- data/vendor/libgit2/src/util.h +13 -5
- data/vendor/libgit2/src/win32/path_w32.c +15 -8
- data/vendor/libgit2/src/win32/posix_w32.c +11 -2
- data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.c +343 -0
- data/vendor/libgit2/src/win32/w32_crtdbg_stacktrace.h +93 -0
- data/vendor/libgit2/src/win32/w32_stack.c +192 -0
- data/vendor/libgit2/src/win32/w32_stack.h +138 -0
- data/vendor/libgit2/src/win32/w32_util.c +29 -5
- data/vendor/libgit2/src/win32/w32_util.h +13 -3
- metadata +11 -5
data/vendor/libgit2/src/util.h
CHANGED
@@ -7,6 +7,9 @@
|
|
7
7
|
#ifndef INCLUDE_util_h__
|
8
8
|
#define INCLUDE_util_h__
|
9
9
|
|
10
|
+
#include "git2/buffer.h"
|
11
|
+
#include "buffer.h"
|
12
|
+
|
10
13
|
#if defined(GIT_MSVC_CRTDBG)
|
11
14
|
/* Enable MSVC CRTDBG memory leak reporting.
|
12
15
|
*
|
@@ -35,6 +38,7 @@
|
|
35
38
|
*/
|
36
39
|
#include <stdlib.h>
|
37
40
|
#include <crtdbg.h>
|
41
|
+
#include "win32/w32_crtdbg_stacktrace.h"
|
38
42
|
#endif
|
39
43
|
|
40
44
|
#include "common.h"
|
@@ -62,23 +66,24 @@
|
|
62
66
|
#define CONST_STRLEN(x) ((sizeof(x)/sizeof(x[0])) - 1)
|
63
67
|
|
64
68
|
#if defined(GIT_MSVC_CRTDBG)
|
69
|
+
|
65
70
|
GIT_INLINE(void *) git__crtdbg__malloc(size_t len, const char *file, int line)
|
66
71
|
{
|
67
|
-
void *ptr = _malloc_dbg(len, _NORMAL_BLOCK, file, line);
|
72
|
+
void *ptr = _malloc_dbg(len, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
|
68
73
|
if (!ptr) giterr_set_oom();
|
69
74
|
return ptr;
|
70
75
|
}
|
71
76
|
|
72
77
|
GIT_INLINE(void *) git__crtdbg__calloc(size_t nelem, size_t elsize, const char *file, int line)
|
73
78
|
{
|
74
|
-
void *ptr = _calloc_dbg(nelem, elsize, _NORMAL_BLOCK, file, line);
|
79
|
+
void *ptr = _calloc_dbg(nelem, elsize, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
|
75
80
|
if (!ptr) giterr_set_oom();
|
76
81
|
return ptr;
|
77
82
|
}
|
78
83
|
|
79
84
|
GIT_INLINE(char *) git__crtdbg__strdup(const char *str, const char *file, int line)
|
80
85
|
{
|
81
|
-
char *ptr = _strdup_dbg(str, _NORMAL_BLOCK, file, line);
|
86
|
+
char *ptr = _strdup_dbg(str, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
|
82
87
|
if (!ptr) giterr_set_oom();
|
83
88
|
return ptr;
|
84
89
|
}
|
@@ -118,7 +123,7 @@ GIT_INLINE(char *) git__crtdbg__substrdup(const char *start, size_t n, const cha
|
|
118
123
|
|
119
124
|
GIT_INLINE(void *) git__crtdbg__realloc(void *ptr, size_t size, const char *file, int line)
|
120
125
|
{
|
121
|
-
void *new_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, file, line);
|
126
|
+
void *new_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
|
122
127
|
if (!new_ptr) giterr_set_oom();
|
123
128
|
return new_ptr;
|
124
129
|
}
|
@@ -126,8 +131,9 @@ GIT_INLINE(void *) git__crtdbg__realloc(void *ptr, size_t size, const char *file
|
|
126
131
|
GIT_INLINE(void *) git__crtdbg__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
|
127
132
|
{
|
128
133
|
size_t newsize;
|
134
|
+
|
129
135
|
return GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize) ?
|
130
|
-
NULL : _realloc_dbg(ptr, newsize, _NORMAL_BLOCK, file, line);
|
136
|
+
NULL : _realloc_dbg(ptr, newsize, _NORMAL_BLOCK, git_win32__crtdbg_stacktrace(1,file), line);
|
131
137
|
}
|
132
138
|
|
133
139
|
GIT_INLINE(void *) git__crtdbg__mallocarray(size_t nelem, size_t elsize, const char *file, int line)
|
@@ -596,4 +602,6 @@ GIT_INLINE(double) git__timer(void)
|
|
596
602
|
|
597
603
|
#endif
|
598
604
|
|
605
|
+
extern int git__getenv(git_buf *out, const char *name);
|
606
|
+
|
599
607
|
#endif /* INCLUDE_util_h__ */
|
@@ -198,13 +198,13 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
|
|
198
198
|
/* See if this is an absolute path (beginning with a drive letter) */
|
199
199
|
if (path__is_absolute(src)) {
|
200
200
|
if (git__utf8_to_16(dest, MAX_PATH, src) < 0)
|
201
|
-
|
201
|
+
goto on_error;
|
202
202
|
}
|
203
203
|
/* File-prefixed NT-style paths beginning with \\?\ */
|
204
204
|
else if (path__is_nt_namespace(src)) {
|
205
205
|
/* Skip the NT prefix, the destination already contains it */
|
206
206
|
if (git__utf8_to_16(dest, MAX_PATH, src + PATH__NT_NAMESPACE_LEN) < 0)
|
207
|
-
|
207
|
+
goto on_error;
|
208
208
|
}
|
209
209
|
/* UNC paths */
|
210
210
|
else if (path__is_unc(src)) {
|
@@ -213,36 +213,43 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
|
|
213
213
|
|
214
214
|
/* Skip the leading "\\" */
|
215
215
|
if (git__utf8_to_16(dest, MAX_PATH - 2, src + 2) < 0)
|
216
|
-
|
216
|
+
goto on_error;
|
217
217
|
}
|
218
218
|
/* Absolute paths omitting the drive letter */
|
219
219
|
else if (src[0] == '\\' || src[0] == '/') {
|
220
220
|
if (path__cwd(dest, MAX_PATH) < 0)
|
221
|
-
|
221
|
+
goto on_error;
|
222
222
|
|
223
223
|
if (!path__is_absolute(dest)) {
|
224
224
|
errno = ENOENT;
|
225
|
-
|
225
|
+
goto on_error;
|
226
226
|
}
|
227
227
|
|
228
228
|
/* Skip the drive letter specification ("C:") */
|
229
229
|
if (git__utf8_to_16(dest + 2, MAX_PATH - 2, src) < 0)
|
230
|
-
|
230
|
+
goto on_error;
|
231
231
|
}
|
232
232
|
/* Relative paths */
|
233
233
|
else {
|
234
234
|
int cwd_len;
|
235
235
|
|
236
236
|
if ((cwd_len = git_win32_path__cwd(dest, MAX_PATH)) < 0)
|
237
|
-
|
237
|
+
goto on_error;
|
238
238
|
|
239
239
|
dest[cwd_len++] = L'\\';
|
240
240
|
|
241
241
|
if (git__utf8_to_16(dest + cwd_len, MAX_PATH - cwd_len, src) < 0)
|
242
|
-
|
242
|
+
goto on_error;
|
243
243
|
}
|
244
244
|
|
245
245
|
return git_win32_path_canonicalize(out);
|
246
|
+
|
247
|
+
on_error:
|
248
|
+
/* set windows error code so we can use its error message */
|
249
|
+
if (errno == ENAMETOOLONG)
|
250
|
+
SetLastError(ERROR_FILENAME_EXCED_RANGE);
|
251
|
+
|
252
|
+
return -1;
|
246
253
|
}
|
247
254
|
|
248
255
|
int git_win32_path_to_utf8(git_win32_utf8_path dest, const wchar_t *src)
|
@@ -11,6 +11,8 @@
|
|
11
11
|
#include "utf-conv.h"
|
12
12
|
#include "repository.h"
|
13
13
|
#include "reparse.h"
|
14
|
+
#include "global.h"
|
15
|
+
#include "buffer.h"
|
14
16
|
#include <errno.h>
|
15
17
|
#include <io.h>
|
16
18
|
#include <fcntl.h>
|
@@ -146,12 +148,19 @@ static int lstat_w(
|
|
146
148
|
return git_win32__file_attribute_to_stat(buf, &fdata, path);
|
147
149
|
}
|
148
150
|
|
149
|
-
|
151
|
+
switch (GetLastError()) {
|
152
|
+
case ERROR_ACCESS_DENIED:
|
153
|
+
errno = EACCES;
|
154
|
+
break;
|
155
|
+
default:
|
156
|
+
errno = ENOENT;
|
157
|
+
break;
|
158
|
+
}
|
150
159
|
|
151
160
|
/* To match POSIX behavior, set ENOTDIR when any of the folders in the
|
152
161
|
* file path is a regular file, otherwise set ENOENT.
|
153
162
|
*/
|
154
|
-
if (posix_enotdir) {
|
163
|
+
if (errno == ENOENT && posix_enotdir) {
|
155
164
|
size_t path_len = wcslen(path);
|
156
165
|
|
157
166
|
/* scan up path until we find an existing item */
|
@@ -0,0 +1,343 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) the libgit2 contributors. All rights reserved.
|
3
|
+
*
|
4
|
+
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
5
|
+
* a Linking Exception. For full terms see the included COPYING file.
|
6
|
+
*/
|
7
|
+
|
8
|
+
#if defined(GIT_MSVC_CRTDBG)
|
9
|
+
#include "w32_stack.h"
|
10
|
+
#include "w32_crtdbg_stacktrace.h"
|
11
|
+
|
12
|
+
#define CRTDBG_STACKTRACE__UID_LEN (15)
|
13
|
+
|
14
|
+
/**
|
15
|
+
* The stacktrace of an allocation can be distilled
|
16
|
+
* to a unique id based upon the stackframe pointers
|
17
|
+
* and ignoring any size arguments. We will use these
|
18
|
+
* UIDs as the (char const*) __FILE__ argument we
|
19
|
+
* give to the CRT malloc routines.
|
20
|
+
*/
|
21
|
+
typedef struct {
|
22
|
+
char uid[CRTDBG_STACKTRACE__UID_LEN + 1];
|
23
|
+
} git_win32__crtdbg_stacktrace__uid;
|
24
|
+
|
25
|
+
/**
|
26
|
+
* All mallocs with the same stacktrace will be de-duped
|
27
|
+
* and aggregated into this row.
|
28
|
+
*/
|
29
|
+
typedef struct {
|
30
|
+
git_win32__crtdbg_stacktrace__uid uid; /* must be first */
|
31
|
+
git_win32__stack__raw_data raw_data;
|
32
|
+
unsigned int count_allocs; /* times this alloc signature seen since init */
|
33
|
+
unsigned int count_allocs_at_last_checkpoint; /* times since last mark */
|
34
|
+
unsigned int transient_count_leaks; /* sum of leaks */
|
35
|
+
} git_win32__crtdbg_stacktrace__row;
|
36
|
+
|
37
|
+
static CRITICAL_SECTION g_crtdbg_stacktrace_cs;
|
38
|
+
|
39
|
+
/**
|
40
|
+
* CRTDBG memory leak tracking takes a "char const * const file_name"
|
41
|
+
* and stores the pointer in the heap data (instead of allocing a copy
|
42
|
+
* for itself). Normally, this is not a problem, since we usually pass
|
43
|
+
* in __FILE__. But I'm going to lie to it and pass in the address of
|
44
|
+
* the UID in place of the file_name. Also, I do not want to alloc the
|
45
|
+
* stacktrace data (because we are called from inside our alloc routines).
|
46
|
+
* Therefore, I'm creating a very large static pool array to store row
|
47
|
+
* data. This also eliminates the temptation to realloc it (and move the
|
48
|
+
* UID pointers).
|
49
|
+
*
|
50
|
+
* And to efficiently look for duplicates we need an index on the rows
|
51
|
+
* so we can bsearch it. Again, without mallocing.
|
52
|
+
*
|
53
|
+
* If we observe more than MY_ROW_LIMIT unique malloc signatures, we
|
54
|
+
* fall through and use the traditional __FILE__ processing and don't
|
55
|
+
* try to de-dup them. If your testing hits this limit, just increase
|
56
|
+
* it and try again.
|
57
|
+
*/
|
58
|
+
|
59
|
+
#define MY_ROW_LIMIT (1024 * 1024)
|
60
|
+
static git_win32__crtdbg_stacktrace__row g_cs_rows[MY_ROW_LIMIT];
|
61
|
+
static git_win32__crtdbg_stacktrace__row *g_cs_index[MY_ROW_LIMIT];
|
62
|
+
|
63
|
+
static unsigned int g_cs_end = MY_ROW_LIMIT;
|
64
|
+
static unsigned int g_cs_ins = 0; /* insertion point == unique allocs seen */
|
65
|
+
static unsigned int g_count_total_allocs = 0; /* number of allocs seen */
|
66
|
+
static unsigned int g_transient_count_total_leaks = 0; /* number of total leaks */
|
67
|
+
static unsigned int g_transient_count_dedup_leaks = 0; /* number of unique leaks */
|
68
|
+
static bool g_limit_reached = false; /* had allocs after we filled row table */
|
69
|
+
|
70
|
+
static unsigned int g_checkpoint_id = 0; /* to better label leak checkpoints */
|
71
|
+
static bool g_transient_leaks_since_mark = false; /* payload for hook */
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Compare function for bsearch on g_cs_index table.
|
75
|
+
*/
|
76
|
+
static int row_cmp(const void *v1, const void *v2)
|
77
|
+
{
|
78
|
+
git_win32__stack__raw_data *d1 = (git_win32__stack__raw_data*)v1;
|
79
|
+
git_win32__crtdbg_stacktrace__row *r2 = (git_win32__crtdbg_stacktrace__row *)v2;
|
80
|
+
|
81
|
+
return (git_win32__stack_compare(d1, &r2->raw_data));
|
82
|
+
}
|
83
|
+
|
84
|
+
/**
|
85
|
+
* Unique insert the new data into the row and index tables.
|
86
|
+
* We have to sort by the stackframe data itself, not the uid.
|
87
|
+
*/
|
88
|
+
static git_win32__crtdbg_stacktrace__row * insert_unique(
|
89
|
+
const git_win32__stack__raw_data *pdata)
|
90
|
+
{
|
91
|
+
size_t pos;
|
92
|
+
if (git__bsearch(g_cs_index, g_cs_ins, pdata, row_cmp, &pos) < 0) {
|
93
|
+
/* Append new unique item to row table. */
|
94
|
+
memcpy(&g_cs_rows[g_cs_ins].raw_data, pdata, sizeof(*pdata));
|
95
|
+
sprintf(g_cs_rows[g_cs_ins].uid.uid, "##%08lx", g_cs_ins);
|
96
|
+
|
97
|
+
/* Insert pointer to it into the proper place in the index table. */
|
98
|
+
if (pos < g_cs_ins)
|
99
|
+
memmove(&g_cs_index[pos+1], &g_cs_index[pos], (g_cs_ins - pos)*sizeof(g_cs_index[0]));
|
100
|
+
g_cs_index[pos] = &g_cs_rows[g_cs_ins];
|
101
|
+
|
102
|
+
g_cs_ins++;
|
103
|
+
}
|
104
|
+
|
105
|
+
g_cs_index[pos]->count_allocs++;
|
106
|
+
|
107
|
+
return g_cs_index[pos];
|
108
|
+
}
|
109
|
+
|
110
|
+
/**
|
111
|
+
* Hook function to receive leak data from the CRT. (This includes
|
112
|
+
* both "<file_name>:(<line_number>)" data, but also each of the
|
113
|
+
* various headers and fields.
|
114
|
+
*
|
115
|
+
* Scan this for the special "##<pos>" UID forms that we substituted
|
116
|
+
* for the "<file_name>". Map <pos> back to the row data and
|
117
|
+
* increment its leak count.
|
118
|
+
*
|
119
|
+
* See https://msdn.microsoft.com/en-us/library/74kabxyx.aspx
|
120
|
+
*
|
121
|
+
* We suppress the actual crtdbg output.
|
122
|
+
*/
|
123
|
+
static int __cdecl report_hook(int nRptType, char *szMsg, int *retVal)
|
124
|
+
{
|
125
|
+
static int hook_result = TRUE; /* FALSE to get stock dump; TRUE to suppress. */
|
126
|
+
unsigned int pos;
|
127
|
+
|
128
|
+
*retVal = 0; /* do not invoke debugger */
|
129
|
+
|
130
|
+
if ((szMsg[0] != '#') || (szMsg[1] != '#'))
|
131
|
+
return hook_result;
|
132
|
+
|
133
|
+
if (sscanf(&szMsg[2], "%08lx", &pos) < 1)
|
134
|
+
return hook_result;
|
135
|
+
if (pos >= g_cs_ins)
|
136
|
+
return hook_result;
|
137
|
+
|
138
|
+
if (g_transient_leaks_since_mark) {
|
139
|
+
if (g_cs_rows[pos].count_allocs == g_cs_rows[pos].count_allocs_at_last_checkpoint)
|
140
|
+
return hook_result;
|
141
|
+
}
|
142
|
+
|
143
|
+
g_cs_rows[pos].transient_count_leaks++;
|
144
|
+
|
145
|
+
if (g_cs_rows[pos].transient_count_leaks == 1)
|
146
|
+
g_transient_count_dedup_leaks++;
|
147
|
+
|
148
|
+
g_transient_count_total_leaks++;
|
149
|
+
|
150
|
+
return hook_result;
|
151
|
+
}
|
152
|
+
|
153
|
+
/**
|
154
|
+
* Write leak data to all of the various places we need.
|
155
|
+
* We force the caller to sprintf() the message first
|
156
|
+
* because we want to avoid fprintf() because it allocs.
|
157
|
+
*/
|
158
|
+
static void my_output(const char *buf)
|
159
|
+
{
|
160
|
+
fwrite(buf, strlen(buf), 1, stderr);
|
161
|
+
OutputDebugString(buf);
|
162
|
+
}
|
163
|
+
|
164
|
+
/**
|
165
|
+
* For each row with leaks, dump a stacktrace for it.
|
166
|
+
*/
|
167
|
+
static void dump_summary(const char *label)
|
168
|
+
{
|
169
|
+
unsigned int k;
|
170
|
+
char buf[10 * 1024];
|
171
|
+
|
172
|
+
if (g_transient_count_total_leaks == 0)
|
173
|
+
return;
|
174
|
+
|
175
|
+
fflush(stdout);
|
176
|
+
fflush(stderr);
|
177
|
+
my_output("\n");
|
178
|
+
|
179
|
+
if (g_limit_reached) {
|
180
|
+
sprintf(buf,
|
181
|
+
"LEAK SUMMARY: de-dup row table[%d] filled. Increase MY_ROW_LIMIT.\n",
|
182
|
+
MY_ROW_LIMIT);
|
183
|
+
my_output(buf);
|
184
|
+
}
|
185
|
+
|
186
|
+
if (!label)
|
187
|
+
label = "";
|
188
|
+
|
189
|
+
if (g_transient_leaks_since_mark) {
|
190
|
+
sprintf(buf, "LEAK CHECKPOINT %d: leaks %d unique %d: %s\n",
|
191
|
+
g_checkpoint_id, g_transient_count_total_leaks, g_transient_count_dedup_leaks, label);
|
192
|
+
my_output(buf);
|
193
|
+
} else {
|
194
|
+
sprintf(buf, "LEAK SUMMARY: TOTAL leaks %d de-duped %d: %s\n",
|
195
|
+
g_transient_count_total_leaks, g_transient_count_dedup_leaks, label);
|
196
|
+
my_output(buf);
|
197
|
+
}
|
198
|
+
my_output("\n");
|
199
|
+
|
200
|
+
for (k = 0; k < g_cs_ins; k++) {
|
201
|
+
if (g_cs_rows[k].transient_count_leaks > 0) {
|
202
|
+
sprintf(buf, "LEAK: %s leaked %d of %d times:\n",
|
203
|
+
g_cs_rows[k].uid.uid,
|
204
|
+
g_cs_rows[k].transient_count_leaks,
|
205
|
+
g_cs_rows[k].count_allocs);
|
206
|
+
my_output(buf);
|
207
|
+
|
208
|
+
if (git_win32__stack_format(
|
209
|
+
buf, sizeof(buf), &g_cs_rows[k].raw_data,
|
210
|
+
NULL, NULL) >= 0) {
|
211
|
+
my_output(buf);
|
212
|
+
}
|
213
|
+
|
214
|
+
my_output("\n");
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
fflush(stderr);
|
219
|
+
}
|
220
|
+
|
221
|
+
void git_win32__crtdbg_stacktrace_init(void)
|
222
|
+
{
|
223
|
+
InitializeCriticalSection(&g_crtdbg_stacktrace_cs);
|
224
|
+
|
225
|
+
EnterCriticalSection(&g_crtdbg_stacktrace_cs);
|
226
|
+
|
227
|
+
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
228
|
+
|
229
|
+
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
|
230
|
+
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
|
231
|
+
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE);
|
232
|
+
|
233
|
+
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
|
234
|
+
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
|
235
|
+
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
|
236
|
+
|
237
|
+
LeaveCriticalSection(&g_crtdbg_stacktrace_cs);
|
238
|
+
}
|
239
|
+
|
240
|
+
int git_win32__crtdbg_stacktrace__dump(
|
241
|
+
git_win32__crtdbg_stacktrace_options opt,
|
242
|
+
const char *label)
|
243
|
+
{
|
244
|
+
_CRT_REPORT_HOOK old;
|
245
|
+
unsigned int k;
|
246
|
+
int r = 0;
|
247
|
+
|
248
|
+
#define IS_BIT_SET(o,b) (((o) & (b)) != 0)
|
249
|
+
|
250
|
+
bool b_set_mark = IS_BIT_SET(opt, GIT_WIN32__CRTDBG_STACKTRACE__SET_MARK);
|
251
|
+
bool b_leaks_since_mark = IS_BIT_SET(opt, GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_SINCE_MARK);
|
252
|
+
bool b_leaks_total = IS_BIT_SET(opt, GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_TOTAL);
|
253
|
+
bool b_quiet = IS_BIT_SET(opt, GIT_WIN32__CRTDBG_STACKTRACE__QUIET);
|
254
|
+
|
255
|
+
if (b_leaks_since_mark && b_leaks_total) {
|
256
|
+
giterr_set(GITERR_INVALID, "Cannot combine LEAKS_SINCE_MARK and LEAKS_TOTAL.");
|
257
|
+
return GIT_ERROR;
|
258
|
+
}
|
259
|
+
if (!b_set_mark && !b_leaks_since_mark && !b_leaks_total) {
|
260
|
+
giterr_set(GITERR_INVALID, "Nothing to do.");
|
261
|
+
return GIT_ERROR;
|
262
|
+
}
|
263
|
+
|
264
|
+
EnterCriticalSection(&g_crtdbg_stacktrace_cs);
|
265
|
+
|
266
|
+
if (b_leaks_since_mark || b_leaks_total) {
|
267
|
+
/* All variables with "transient" in the name are per-dump counters
|
268
|
+
* and reset before each dump. This lets us handle checkpoints.
|
269
|
+
*/
|
270
|
+
g_transient_count_total_leaks = 0;
|
271
|
+
g_transient_count_dedup_leaks = 0;
|
272
|
+
for (k = 0; k < g_cs_ins; k++) {
|
273
|
+
g_cs_rows[k].transient_count_leaks = 0;
|
274
|
+
}
|
275
|
+
}
|
276
|
+
|
277
|
+
g_transient_leaks_since_mark = b_leaks_since_mark;
|
278
|
+
|
279
|
+
old = _CrtSetReportHook(report_hook);
|
280
|
+
_CrtDumpMemoryLeaks();
|
281
|
+
_CrtSetReportHook(old);
|
282
|
+
|
283
|
+
if (b_leaks_since_mark || b_leaks_total) {
|
284
|
+
r = g_transient_count_dedup_leaks;
|
285
|
+
|
286
|
+
if (!b_quiet)
|
287
|
+
dump_summary(label);
|
288
|
+
}
|
289
|
+
|
290
|
+
if (b_set_mark) {
|
291
|
+
for (k = 0; k < g_cs_ins; k++) {
|
292
|
+
g_cs_rows[k].count_allocs_at_last_checkpoint = g_cs_rows[k].count_allocs;
|
293
|
+
}
|
294
|
+
|
295
|
+
g_checkpoint_id++;
|
296
|
+
}
|
297
|
+
|
298
|
+
LeaveCriticalSection(&g_crtdbg_stacktrace_cs);
|
299
|
+
|
300
|
+
return r;
|
301
|
+
}
|
302
|
+
|
303
|
+
void git_win32__crtdbg_stacktrace_cleanup(void)
|
304
|
+
{
|
305
|
+
/* At shutdown/cleanup, dump cummulative leak info
|
306
|
+
* with everything since startup. This might generate
|
307
|
+
* extra noise if the caller has been doing checkpoint
|
308
|
+
* dumps, but it might also eliminate some false
|
309
|
+
* positives for resources previously reported during
|
310
|
+
* checkpoints.
|
311
|
+
*/
|
312
|
+
git_win32__crtdbg_stacktrace__dump(
|
313
|
+
GIT_WIN32__CRTDBG_STACKTRACE__LEAKS_TOTAL,
|
314
|
+
"CLEANUP");
|
315
|
+
|
316
|
+
DeleteCriticalSection(&g_crtdbg_stacktrace_cs);
|
317
|
+
}
|
318
|
+
|
319
|
+
const char *git_win32__crtdbg_stacktrace(int skip, const char *file)
|
320
|
+
{
|
321
|
+
git_win32__stack__raw_data new_data;
|
322
|
+
git_win32__crtdbg_stacktrace__row *row;
|
323
|
+
const char * result = file;
|
324
|
+
|
325
|
+
if (git_win32__stack_capture(&new_data, skip+1) < 0)
|
326
|
+
return result;
|
327
|
+
|
328
|
+
EnterCriticalSection(&g_crtdbg_stacktrace_cs);
|
329
|
+
|
330
|
+
if (g_cs_ins < g_cs_end) {
|
331
|
+
row = insert_unique(&new_data);
|
332
|
+
result = row->uid.uid;
|
333
|
+
} else {
|
334
|
+
g_limit_reached = true;
|
335
|
+
}
|
336
|
+
|
337
|
+
g_count_total_allocs++;
|
338
|
+
|
339
|
+
LeaveCriticalSection(&g_crtdbg_stacktrace_cs);
|
340
|
+
|
341
|
+
return result;
|
342
|
+
}
|
343
|
+
#endif
|