Import the current version of talloc from the Samba 3 source base. This gives

us greater confidence that our talloc implementation is "known good".  Remove
the OOM handling from consider_message: talloc_set_fail_handler is no longer
supported.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
This commit is contained in:
emellor@leeni.uk.xensource.com committed 2006-03-23 14:32:15 +01:00
1 parent 64444a6982
commit 1bac3b49cd
4 files changed
+278 -133

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
The following files are imported from the Samba project. We use the versions
from Samba 3, the current stable branch.
talloc.c: samba-trunk/source/lib/talloc.c r14291 2006-03-13 04:27:47 +0000
talloc.h: samba-trunk/source/include/talloc.h r11986 2005-12-01 00:43:36 +0000
+250 -98
View File
@@ -1,4 +1,4 @@
/*
/*
Samba Unix SMB/CIFS implementation.
Samba trivial allocation library - new interface
@@ -6,27 +6,30 @@
NOTE: Please read talloc_guide.txt for full documentation
Copyright (C) Andrew Tridgell 2004
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
** NOTE! The following LGPL license applies to the talloc
** library. This does NOT imply that all of Samba is released
** under the LGPL
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
inspired by http://swapped.cc/halloc/
*/
#ifdef _SAMBA_BUILD_
#include "includes.h"
#if ((SAMBA_VERSION_MAJOR==3)&&(SAMBA_VERSION_MINOR<9))
@@ -52,15 +55,13 @@
/* use this to force every realloc to change the pointer, to stress test
code that might not cope */
#ifdef TESTING
#define ALWAYS_REALLOC 1
void *test_malloc(size_t size);
#define malloc test_malloc
#endif
#define ALWAYS_REALLOC 0
#define MAX_TALLOC_SIZE 0x10000000
#define TALLOC_MAGIC 0xe814ec4f
#define TALLOC_MAGIC_FREE 0x7faebef3
#define TALLOC_MAGIC 0xe814ec70
#define TALLOC_FLAG_FREE 0x01
#define TALLOC_FLAG_LOOP 0x02
#define TALLOC_MAGIC_REFERENCE ((const char *)1)
/* by default we abort when given a bad pointer (such as when talloc_free() is called
@@ -83,8 +84,7 @@ void *test_malloc(size_t size);
*/
static const void *null_context;
static void *cleanup_context;
static int (*malloc_fail_handler)(void *);
static void *malloc_fail_data;
struct talloc_reference_handle {
struct talloc_reference_handle *next, *prev;
@@ -97,24 +97,27 @@ struct talloc_chunk {
struct talloc_chunk *next, *prev;
struct talloc_chunk *parent, *child;
struct talloc_reference_handle *refs;
size_t size;
unsigned magic;
talloc_destructor_t destructor;
const char *name;
size_t size;
unsigned flags;
};
/* 16 byte alignment seems to keep everyone happy */
#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15)
#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc))
/* panic if we get a bad magic value */
static struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr)
{
struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, ptr)-1;
if (tc->magic != TALLOC_MAGIC) {
if (tc->magic == TALLOC_MAGIC_FREE) {
TALLOC_ABORT("Bad talloc magic value - double free");
} else {
TALLOC_ABORT("Bad talloc magic value - unknown value");
}
const char *pp = ptr;
struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE);
if ((tc->flags & ~0xF) != TALLOC_MAGIC) {
TALLOC_ABORT("Bad talloc magic value - unknown value");
}
if (tc->flags & TALLOC_FLAG_FREE) {
TALLOC_ABORT("Bad talloc magic value - double free");
}
return tc;
}
@@ -159,7 +162,7 @@ static struct talloc_chunk *talloc_parent_chunk(const void *ptr)
void *talloc_parent(const void *ptr)
{
struct talloc_chunk *tc = talloc_parent_chunk(ptr);
return (void *)(tc+1);
return tc? TC_PTR_FROM_CHUNK(tc) : NULL;
}
/*
@@ -177,17 +180,11 @@ void *_talloc(const void *context, size_t size)
return NULL;
}
tc = malloc(sizeof(*tc)+size);
if (tc == NULL) {
if (malloc_fail_handler)
if (malloc_fail_handler(malloc_fail_data))
tc = malloc(sizeof(*tc)+size);
if (!tc)
return NULL;
}
tc = malloc(TC_HDR_SIZE+size);
if (tc == NULL) return NULL;
tc->size = size;
tc->magic = TALLOC_MAGIC;
tc->flags = TALLOC_MAGIC;
tc->destructor = NULL;
tc->child = NULL;
tc->name = NULL;
@@ -207,7 +204,7 @@ void *_talloc(const void *context, size_t size)
tc->next = tc->prev = tc->parent = NULL;
}
return (void *)(tc+1);
return TC_PTR_FROM_CHUNK(tc);
}
@@ -292,7 +289,11 @@ static int talloc_unreference(const void *context, const void *ptr)
for (h=tc->refs;h;h=h->next) {
struct talloc_chunk *p = talloc_parent_chunk(h);
if ((p==NULL && context==NULL) || p+1 == context) break;
if (p == NULL) {
if (context == NULL) break;
} else if (TC_PTR_FROM_CHUNK(p) == context) {
break;
}
}
if (h == NULL) {
return -1;
@@ -343,7 +344,7 @@ int talloc_unlink(const void *context, void *ptr)
new_p = talloc_parent_chunk(tc_p->refs);
if (new_p) {
new_parent = new_p+1;
new_parent = TC_PTR_FROM_CHUNK(new_p);
} else {
new_parent = NULL;
}
@@ -471,6 +472,8 @@ void *talloc_init(const char *fmt, ...)
va_list ap;
void *ptr;
talloc_enable_null_tracking();
ptr = _talloc(NULL, 0);
if (ptr == NULL) return NULL;
@@ -502,16 +505,16 @@ void talloc_free_children(void *ptr)
choice is owner of any remaining reference to this
pointer, the second choice is our parent, and the
final choice is the null context. */
void *child = tc->child+1;
void *child = TC_PTR_FROM_CHUNK(tc->child);
const void *new_parent = null_context;
if (tc->child->refs) {
struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
if (p) new_parent = p+1;
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
}
if (talloc_free(child) == -1) {
if (new_parent == null_context) {
struct talloc_chunk *p = talloc_parent_chunk(ptr);
if (p) new_parent = p+1;
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
}
talloc_steal(new_parent, child);
}
@@ -541,6 +544,11 @@ int talloc_free(void *ptr)
return -1;
}
if (tc->flags & TALLOC_FLAG_LOOP) {
/* we have a free loop - stop looping */
return 0;
}
if (tc->destructor) {
talloc_destructor_t d = tc->destructor;
if (d == (talloc_destructor_t)-1) {
@@ -554,6 +562,8 @@ int talloc_free(void *ptr)
tc->destructor = NULL;
}
tc->flags |= TALLOC_FLAG_LOOP;
talloc_free_children(ptr);
if (tc->parent) {
@@ -566,7 +576,7 @@ int talloc_free(void *ptr)
if (tc->next) tc->next->prev = tc->prev;
}
tc->magic = TALLOC_MAGIC_FREE;
tc->flags |= TALLOC_FLAG_FREE;
free(tc);
return 0;
@@ -606,36 +616,24 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n
}
/* by resetting magic we catch users of the old memory */
tc->magic = TALLOC_MAGIC_FREE;
tc->flags |= TALLOC_FLAG_FREE;
#if ALWAYS_REALLOC
new_ptr = malloc(size + sizeof(*tc));
if (!new_ptr) {
tc->magic = TALLOC_MAGIC;
if (malloc_fail_handler)
if (malloc_fail_handler(malloc_fail_data))
new_ptr = malloc(size + sizeof(*tc));
}
new_ptr = malloc(size + TC_HDR_SIZE);
if (new_ptr) {
memcpy(new_ptr, tc, tc->size + sizeof(*tc));
memcpy(new_ptr, tc, tc->size + TC_HDR_SIZE);
free(tc);
}
#else
new_ptr = realloc(tc, size + sizeof(*tc));
if (!new_ptr) {
tc->magic = TALLOC_MAGIC;
if (malloc_fail_handler)
if (malloc_fail_handler(malloc_fail_data))
new_ptr = realloc(tc, size + sizeof(*tc));
}
new_ptr = realloc(tc, size + TC_HDR_SIZE);
#endif
if (!new_ptr) {
tc->magic = TALLOC_MAGIC;
tc->flags &= ~TALLOC_FLAG_FREE;
return NULL;
}
tc = new_ptr;
tc->magic = TALLOC_MAGIC;
tc->flags &= ~TALLOC_FLAG_FREE;
if (tc->parent) {
tc->parent->child = new_ptr;
}
@@ -651,9 +649,9 @@ void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *n
}
tc->size = size;
talloc_set_name_const(tc+1, name);
talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name);
return (void *)(tc+1);
return TC_PTR_FROM_CHUNK(tc);
}
/*
@@ -730,10 +728,19 @@ off_t talloc_total_size(const void *ptr)
tc = talloc_chunk_from_ptr(ptr);
if (tc->flags & TALLOC_FLAG_LOOP) {
return 0;
}
tc->flags |= TALLOC_FLAG_LOOP;
total = tc->size;
for (c=tc->child;c;c=c->next) {
total += talloc_total_size(c+1);
total += talloc_total_size(TC_PTR_FROM_CHUNK(c));
}
tc->flags &= ~TALLOC_FLAG_LOOP;
return total;
}
@@ -743,20 +750,21 @@ off_t talloc_total_size(const void *ptr)
off_t talloc_total_blocks(const void *ptr)
{
off_t total = 0;
struct talloc_chunk *c, *tc;
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
if (ptr == NULL) {
ptr = null_context;
}
if (ptr == NULL) {
if (tc->flags & TALLOC_FLAG_LOOP) {
return 0;
}
tc = talloc_chunk_from_ptr(ptr);
tc->flags |= TALLOC_FLAG_LOOP;
total++;
for (c=tc->child;c;c=c->next) {
total += talloc_total_blocks(c+1);
total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c));
}
tc->flags &= ~TALLOC_FLAG_LOOP;
return total;
}
@@ -782,23 +790,29 @@ void talloc_report_depth(const void *ptr, FILE *f, int depth)
{
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
if (tc->flags & TALLOC_FLAG_LOOP) {
return;
}
tc->flags |= TALLOC_FLAG_LOOP;
for (c=tc->child;c;c=c->next) {
if (c->name == TALLOC_MAGIC_REFERENCE) {
struct talloc_reference_handle *handle = (void *)(c+1);
struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
const char *name2 = talloc_get_name(handle->ptr);
fprintf(f, "%*sreference to: %s\n", depth*4, "", name2);
} else {
const char *name = talloc_get_name(c+1);
const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
depth*4, "",
name,
(unsigned long)talloc_total_size(c+1),
(unsigned long)talloc_total_blocks(c+1),
talloc_reference_count(c+1));
talloc_report_depth(c+1, f, depth+1);
(unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
(unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
talloc_report_depth(TC_PTR_FROM_CHUNK(c), f, depth+1);
}
}
tc->flags &= ~TALLOC_FLAG_LOOP;
}
/*
@@ -841,9 +855,9 @@ void talloc_report(const void *ptr, FILE *f)
for (c=tc->child;c;c=c->next) {
fprintf(f, "\t%-30s contains %6lu bytes in %3lu blocks\n",
talloc_get_name(c+1),
(unsigned long)talloc_total_size(c+1),
(unsigned long)talloc_total_blocks(c+1));
talloc_get_name(TC_PTR_FROM_CHUNK(c)),
(unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
(unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)));
}
fflush(f);
}
@@ -878,6 +892,74 @@ void talloc_enable_null_tracking(void)
}
}
#ifdef _SAMBA_BUILD_
/* Ugly calls to Samba-specific sprintf_append... JRA. */
/*
report on memory usage by all children of a pointer, giving a full tree view
*/
static void talloc_report_depth_str(const void *ptr, char **pps, ssize_t *plen, size_t *pbuflen, int depth)
{
struct talloc_chunk *c, *tc = talloc_chunk_from_ptr(ptr);
if (tc->flags & TALLOC_FLAG_LOOP) {
return;
}
tc->flags |= TALLOC_FLAG_LOOP;
for (c=tc->child;c;c=c->next) {
if (c->name == TALLOC_MAGIC_REFERENCE) {
struct talloc_reference_handle *handle = TC_PTR_FROM_CHUNK(c);
const char *name2 = talloc_get_name(handle->ptr);
sprintf_append(NULL, pps, plen, pbuflen,
"%*sreference to: %s\n", depth*4, "", name2);
} else {
const char *name = talloc_get_name(TC_PTR_FROM_CHUNK(c));
sprintf_append(NULL, pps, plen, pbuflen,
"%*s%-30s contains %6lu bytes in %3lu blocks (ref %d)\n",
depth*4, "",
name,
(unsigned long)talloc_total_size(TC_PTR_FROM_CHUNK(c)),
(unsigned long)talloc_total_blocks(TC_PTR_FROM_CHUNK(c)),
talloc_reference_count(TC_PTR_FROM_CHUNK(c)));
talloc_report_depth_str(TC_PTR_FROM_CHUNK(c), pps, plen, pbuflen, depth+1);
}
}
tc->flags &= ~TALLOC_FLAG_LOOP;
}
/*
report on memory usage by all children of a pointer
*/
char *talloc_describe_all(void)
{
ssize_t len = 0;
size_t buflen = 512;
char *s = NULL;
if (null_context == NULL) {
return NULL;
}
sprintf_append(NULL, &s, &len, &buflen,
"full talloc report on '%s' (total %lu bytes in %lu blocks)\n",
talloc_get_name(null_context),
(unsigned long)talloc_total_size(null_context),
(unsigned long)talloc_total_blocks(null_context));
if (!s) {
return NULL;
}
talloc_report_depth_str(null_context, &s, &len, &buflen, 1);
return s;
}
#endif
/*
enable leak reporting on exit
*/
@@ -941,6 +1023,30 @@ char *talloc_strdup(const void *t, const char *p)
return ret;
}
/*
append to a talloced string
*/
char *talloc_append_string(const void *t, char *orig, const char *append)
{
char *ret;
size_t olen = strlen(orig);
size_t alenz;
if (!append)
return orig;
alenz = strlen(append) + 1;
ret = talloc_realloc(t, orig, char, olen + alenz);
if (!ret)
return NULL;
/* append the string with the trailing \0 */
memcpy(&ret[olen], append, alenz);
return ret;
}
/*
strndup with a talloc
*/
@@ -949,7 +1055,7 @@ char *talloc_strndup(const void *t, const char *p, size_t n)
size_t len;
char *ret;
for (len=0; p[len] && len<n; len++) ;
for (len=0; len<n && p[len]; len++) ;
ret = _talloc(t, len + 1);
if (!ret) { return NULL; }
@@ -974,10 +1080,14 @@ char *talloc_vasprintf(const void *t, const char *fmt, va_list ap)
int len;
char *ret;
va_list ap2;
char c;
VA_COPY(ap2, ap);
len = vsnprintf(NULL, 0, fmt, ap2);
/* this call looks strange, but it makes it work on older solaris boxes */
if ((len = vsnprintf(&c, 1, fmt, ap2)) < 0) {
return NULL;
}
ret = _talloc(t, len+1);
if (ret) {
@@ -1029,7 +1139,15 @@ static char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap)
VA_COPY(ap2, ap);
s_len = tc->size - 1;
len = vsnprintf(NULL, 0, fmt, ap2);
if ((len = vsnprintf(NULL, 0, fmt, ap2)) <= 0) {
/* Either the vsnprintf failed or the format resulted in
* no characters being formatted. In the former case, we
* ought to return NULL, in the latter we ought to return
* the original string. Most current callers of this
* function expect it to never return NULL.
*/
return s;
}
s = talloc_realloc(NULL, s, char, s_len + len+1);
if (!s) return NULL;
@@ -1133,11 +1251,45 @@ size_t talloc_get_size(const void *context)
return tc->size;
}
talloc_fail_handler *talloc_set_fail_handler(talloc_fail_handler *handler,
void *data)
/*
find a parent of this context that has the given name, if any
*/
void *talloc_find_parent_byname(const void *context, const char *name)
{
talloc_fail_handler *old = malloc_fail_handler;
malloc_fail_handler = handler;
malloc_fail_data = data;
return old;
struct talloc_chunk *tc;
if (context == NULL) {
return NULL;
}
tc = talloc_chunk_from_ptr(context);
while (tc) {
if (tc->name && strcmp(tc->name, name) == 0) {
return TC_PTR_FROM_CHUNK(tc);
}
while (tc && tc->prev) tc = tc->prev;
tc = tc->parent;
}
return NULL;
}
/*
show the parentage of a context
*/
void talloc_show_parents(const void *context, FILE *file)
{
struct talloc_chunk *tc;
if (context == NULL) {
fprintf(file, "talloc no parents for NULL\n");
return;
}
tc = talloc_chunk_from_ptr(context);
fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context));
while (tc) {
fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc)));
while (tc && tc->prev) tc = tc->prev;
tc = tc->parent;
}
}
+23 -13
View File
@@ -6,19 +6,23 @@
Copyright (C) Andrew Tridgell 2004-2005
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
** NOTE! The following LGPL license applies to the talloc
** library. This does NOT imply that all of Samba is released
** under the LGPL
This program is distributed in the hope that it will be useful,
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* this is only needed for compatibility with the old talloc */
@@ -58,13 +62,18 @@ typedef void TALLOC_CTX;
#define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count)
#define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count)
#if 0
/* Not correct for Samba3. */
#define data_blob(ptr, size) data_blob_named(ptr, size, "DATA_BLOB: "__location__)
#define data_blob_talloc(ctx, ptr, size) data_blob_talloc_named(ctx, ptr, size, "DATA_BLOB: "__location__)
#define data_blob_dup_talloc(ctx, blob) data_blob_talloc_named(ctx, (blob)->data, (blob)->length, "DATA_BLOB: "__location__)
#endif
#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type)
#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type)
#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type)
#if TALLOC_DEPRECATED
#define talloc_zero_p(ctx, type) talloc_zero(ctx, type)
@@ -117,6 +126,7 @@ void *_talloc_zero(const void *ctx, size_t size, const char *name);
void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name);
char *talloc_strdup(const void *t, const char *p);
char *talloc_strndup(const void *t, const char *p, size_t n);
char *talloc_append_string(const void *t, char *orig, const char *append);
char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0);
char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3);
char *talloc_asprintf_append(char *s,
@@ -127,8 +137,8 @@ void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned
void *talloc_realloc_fn(const void *context, void *ptr, size_t size);
void *talloc_autofree_context(void);
size_t talloc_get_size(const void *ctx);
void *talloc_find_parent_byname(const void *ctx, const char *name);
void talloc_show_parents(const void *context, FILE *file);
typedef int talloc_fail_handler(void *);
talloc_fail_handler *talloc_set_fail_handler(talloc_fail_handler *, void *);
#endif
-22
View File
@@ -1231,39 +1231,17 @@ static void process_message(struct connection *conn, struct buffered_data *in)
conn->transaction = NULL;
}
static int out_of_mem(void *data)
{
longjmp(*(jmp_buf *)data, 1);
}
static void consider_message(struct connection *conn)
{
jmp_buf talloc_fail;
if (verbose)
xprintf("Got message %s len %i from %p\n",
sockmsg_string(conn->in->hdr.msg.type),
conn->in->hdr.msg.len, conn);
/* For simplicity, we kill the connection on OOM. */
talloc_set_fail_handler(out_of_mem, &talloc_fail);
if (setjmp(talloc_fail)) {
talloc_free(conn);
goto end;
}
process_message(conn, conn->in);
talloc_free(conn->in);
conn->in = new_buffer(conn);
end:
talloc_set_fail_handler(NULL, NULL);
if (talloc_total_blocks(NULL)
!= talloc_total_blocks(talloc_autofree_context()) + 1) {
talloc_report_full(NULL, stderr);
abort();
}
}
/* Errors in reading or allocating here mean we get out of sync, so we
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.