mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-11-10 10:05:09 +03:00
Fix a refcount bug.
This commit is contained in:
parent
27c67acca4
commit
3c6398c106
19
g/a.c
19
g/a.c
@ -900,6 +900,25 @@ u3_ca_use(u3_noun som)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* u3_ca_audit(): investigate object.
|
||||||
|
*/
|
||||||
|
c3_o
|
||||||
|
u3_ca_audit(u3_noun som)
|
||||||
|
{
|
||||||
|
if ( u3_so(u3_co_is_cat(som)) ) {
|
||||||
|
return u3_yes;
|
||||||
|
}
|
||||||
|
if ( 0 == u3_ca_use(som) ) {
|
||||||
|
u3_cm_p("som", som);
|
||||||
|
printf("zero: %x/%x\r\n", u3_cr_mug(som), som);
|
||||||
|
return u3_no;
|
||||||
|
}
|
||||||
|
else if ( u3_so(u3du(som)) ) {
|
||||||
|
return u3_and(u3_ca_audit(u3h(som)), u3_ca_audit(u3t(som)));
|
||||||
|
}
|
||||||
|
else return u3_yes;
|
||||||
|
}
|
||||||
|
|
||||||
/* u3_ca_slab(): create a length-bounded proto-atom.
|
/* u3_ca_slab(): create a length-bounded proto-atom.
|
||||||
*/
|
*/
|
||||||
c3_w*
|
c3_w*
|
||||||
|
18
g/j.c
18
g/j.c
@ -82,11 +82,10 @@ u3_cj_find(u3_noun bat)
|
|||||||
{
|
{
|
||||||
u3_cs_road* rod_u = u3R;
|
u3_cs_road* rod_u = u3R;
|
||||||
|
|
||||||
while ( rod_u->par_u ) {
|
while ( rod_u->par_u && u3_so(u3_co_is_senior(rod_u, bat)) ) {
|
||||||
if ( u3_so(u3_co_is_senior(rod_u, bat)) ) {
|
rod_u = rod_u->par_u;
|
||||||
rod_u = rod_u->par_u;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
u3_weak jax = u3_ch_get(rod_u->jed.har_u, bat);
|
u3_weak jax = u3_ch_get(rod_u->jed.har_u, bat);
|
||||||
|
|
||||||
@ -519,10 +518,8 @@ _cj_save(u3_noun bat,
|
|||||||
u3_cs_road* rod_u = u3R;
|
u3_cs_road* rod_u = u3R;
|
||||||
u3_cs_road* tmp_u;
|
u3_cs_road* tmp_u;
|
||||||
|
|
||||||
while ( rod_u->par_u ) {
|
while ( rod_u->par_u && u3_so(u3_co_is_senior(rod_u, bat)) ) {
|
||||||
if ( u3_so(u3_co_is_senior(rod_u, bat)) ) {
|
rod_u = rod_u->par_u;
|
||||||
rod_u = rod_u->par_u;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_u = u3R;
|
tmp_u = u3R;
|
||||||
@ -644,9 +641,10 @@ u3_cj_mine(u3_noun clu,
|
|||||||
u3D.ray_u[jax_l].par_u = par_u;
|
u3D.ray_u[jax_l].par_u = par_u;
|
||||||
c3_assert(0 != jax_l);
|
c3_assert(0 != jax_l);
|
||||||
free(nam_c);
|
free(nam_c);
|
||||||
|
#if 0
|
||||||
fprintf(stderr, "mine: bound jet %d/%s\r\n",
|
fprintf(stderr, "mine: bound jet %d/%s\r\n",
|
||||||
cop_u->jax_l, cop_u->cos_c);
|
cop_u->jax_l, cop_u->cos_c);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i_l++;
|
i_l++;
|
||||||
@ -662,7 +660,7 @@ u3_cj_mine(u3_noun clu,
|
|||||||
fak_u.axe_l = axe_l;
|
fak_u.axe_l = axe_l;
|
||||||
|
|
||||||
jax_l = _cj_insert(&fak_u);
|
jax_l = _cj_insert(&fak_u);
|
||||||
fprintf(stderr, "mine: dummy jet %d/%s\r\n", jax_l, fak_u.cos_c);
|
// fprintf(stderr, "mine: dummy jet %d/%s\r\n", jax_l, fak_u.cos_c);
|
||||||
}
|
}
|
||||||
u3z(clu);
|
u3z(clu);
|
||||||
|
|
||||||
|
135
g/m.c
135
g/m.c
@ -10,8 +10,7 @@
|
|||||||
|
|
||||||
#include "all.h"
|
#include "all.h"
|
||||||
|
|
||||||
static jmp_buf Signal_u;
|
static jmp_buf u3_Signal;
|
||||||
static c3_l Signal_l;
|
|
||||||
|
|
||||||
#ifndef SIGSTKSZ
|
#ifndef SIGSTKSZ
|
||||||
# define SIGSTKSZ 16384
|
# define SIGSTKSZ 16384
|
||||||
@ -24,7 +23,7 @@ void u3_unix_ef_move(void); // restore system signal regime
|
|||||||
extern void
|
extern void
|
||||||
u3_lo_sway(c3_l tab_l, u3_noun tax);
|
u3_lo_sway(c3_l tab_l, u3_noun tax);
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
/* _cm_punt(): crudely print trace.
|
/* _cm_punt(): crudely print trace.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
@ -53,19 +52,12 @@ _cm_emergency(c3_c* cap_c, c3_l sig_l)
|
|||||||
write(2, "\r\n", 2);
|
write(2, "\r\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _cm_overflow_over(void *arg1, void *arg2, void *arg3)
|
static void _cm_overflow(void *arg1, void *arg2, void *arg3)
|
||||||
{
|
{
|
||||||
(void)(arg1);
|
(void)(arg1);
|
||||||
(void)(arg2);
|
(void)(arg2);
|
||||||
(void)(arg3);
|
(void)(arg3);
|
||||||
siglongjmp(Signal_u, c3__over);
|
siglongjmp(u3_Signal, c3__over);
|
||||||
}
|
|
||||||
static void _cm_overflow_dire(void *arg1, void *arg2, void *arg3)
|
|
||||||
{
|
|
||||||
(void)(arg1);
|
|
||||||
(void)(arg2);
|
|
||||||
(void)(arg3);
|
|
||||||
siglongjmp(Signal_u, c3__dire);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* _cm_signal_handle(): handle a signal in general.
|
/* _cm_signal_handle(): handle a signal in general.
|
||||||
@ -73,33 +65,11 @@ static void _cm_overflow_dire(void *arg1, void *arg2, void *arg3)
|
|||||||
static void
|
static void
|
||||||
_cm_signal_handle(c3_l sig_l)
|
_cm_signal_handle(c3_l sig_l)
|
||||||
{
|
{
|
||||||
c3_l org_l = sig_l;
|
if ( c3__over == sig_l ) {
|
||||||
|
sigsegv_leave_handler(_cm_overflow, NULL, NULL, NULL);
|
||||||
_cm_emergency("signal", sig_l);
|
|
||||||
|
|
||||||
if ( Signal_l || (u3R == &u3H->rod_u) ) {
|
|
||||||
_cm_emergency("signal overlap: old", Signal_l);
|
|
||||||
_cm_emergency("signal overlap: new", sig_l);
|
|
||||||
|
|
||||||
if ( c3__prof == sig_l ) {
|
|
||||||
// Ignore strange profiling event.
|
|
||||||
//
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sig_l = c3__dire;
|
|
||||||
}
|
|
||||||
Signal_l = sig_l;
|
|
||||||
|
|
||||||
if ( c3__over == org_l ) {
|
|
||||||
if ( c3__dire == sig_l ) {
|
|
||||||
sigsegv_leave_handler(_cm_overflow_dire, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sigsegv_leave_handler(_cm_overflow_over, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
siglongjmp(Signal_u, sig_l);
|
siglongjmp(u3_Signal, sig_l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,6 +88,7 @@ _cm_signal_handle_term(int x)
|
|||||||
static void
|
static void
|
||||||
_cm_signal_handle_intr(int x)
|
_cm_signal_handle_intr(int x)
|
||||||
{
|
{
|
||||||
|
abort();
|
||||||
_cm_signal_handle(c3__intr);
|
_cm_signal_handle(c3__intr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,21 +111,45 @@ _cm_signal_reset(void)
|
|||||||
/* _cm_signal_recover(): recover from a deep signal, after longjmp.
|
/* _cm_signal_recover(): recover from a deep signal, after longjmp.
|
||||||
*/
|
*/
|
||||||
static u3_noun
|
static u3_noun
|
||||||
_cm_signal_recover(void)
|
_cm_signal_recover(c3_l sig_l)
|
||||||
{
|
{
|
||||||
_cm_emergency("recover", Signal_l);
|
u3_noun tax;
|
||||||
|
|
||||||
if ( c3__dire == Signal_l ) {
|
// XX: special handling for profile signal.
|
||||||
Signal_l = 0;
|
//
|
||||||
|
|
||||||
|
// Unlikely to be set, but it can be made to happen.
|
||||||
|
//
|
||||||
|
tax = u3R->bug.tax;
|
||||||
|
u3R->bug.tax = 0;
|
||||||
|
|
||||||
|
if ( &(u3H->rod_u) == u3R ) {
|
||||||
|
// A top-level crash - rather odd. We should GC here.
|
||||||
|
//
|
||||||
|
_cm_emergency("recover: top", sig_l);
|
||||||
|
|
||||||
|
// Reset the top road - the problem could be a fat cap.
|
||||||
|
//
|
||||||
_cm_signal_reset();
|
_cm_signal_reset();
|
||||||
return u3nt(3, c3__dire, 0);
|
|
||||||
|
if ( (c3__meme == sig_l) && (u3_co_open(u3R) <= 256) ) {
|
||||||
|
// Out of memory at the top level. Error becomes c3__full,
|
||||||
|
// and we release the emergency buffer. To continue work,
|
||||||
|
// we need to readjust the image, eg, migrate to 64 bit.
|
||||||
|
//
|
||||||
|
u3z(u3R->bug.mer);
|
||||||
|
sig_l = c3__full;
|
||||||
|
}
|
||||||
|
return u3nt(3, sig_l, tax);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
u3_noun tax = u3_nul;
|
|
||||||
u3_noun pro;
|
u3_noun pro;
|
||||||
|
|
||||||
// Descend to the road that caused the problem - in almost all
|
// A signal was generated while we were within Nock.
|
||||||
// cases the innermost road, except for a
|
//
|
||||||
|
_cm_emergency("recover: dig", sig_l);
|
||||||
|
|
||||||
|
// Descend to the innermost trace, collecting stack.
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
u3_cs_road* rod_u;
|
u3_cs_road* rod_u;
|
||||||
@ -167,13 +162,12 @@ _cm_signal_recover(void)
|
|||||||
rod_u = rod_u->kid_u;
|
rod_u = rod_u->kid_u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u3_lo_sway(2, u3k(tax)); // XX
|
||||||
|
abort(); // XX
|
||||||
|
pro = u3nt(3, sig_l, tax);
|
||||||
_cm_signal_reset();
|
_cm_signal_reset();
|
||||||
pro = u3nt(3, Signal_l, tax);
|
|
||||||
|
|
||||||
_cm_punt(tax);
|
|
||||||
u3_lo_sway(2, u3k(tax));
|
|
||||||
|
|
||||||
Signal_l = 0;
|
|
||||||
return pro;
|
return pro;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,6 +216,14 @@ _cm_signal_done()
|
|||||||
u3_unix_ef_move();
|
u3_unix_ef_move();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* u3_cm_signal(): treat a nock-level exception as a signal interrupt.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
u3_cm_signal(u3_noun sig_l)
|
||||||
|
{
|
||||||
|
siglongjmp(u3_Signal, sig_l);
|
||||||
|
}
|
||||||
|
|
||||||
/* u3_cm_file(): load file, as atom, or bail.
|
/* u3_cm_file(): load file, as atom, or bail.
|
||||||
*/
|
*/
|
||||||
u3_noun
|
u3_noun
|
||||||
@ -323,6 +325,7 @@ _boot_parts(void)
|
|||||||
{
|
{
|
||||||
u3R->cax.har_u = u3_ch_new();
|
u3R->cax.har_u = u3_ch_new();
|
||||||
u3R->jed.har_u = u3_ch_new();
|
u3R->jed.har_u = u3_ch_new();
|
||||||
|
u3R->bug.mer = u3_ci_tape("emergency buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* u3_cm_boot(): instantiate or activate image.
|
/* u3_cm_boot(): instantiate or activate image.
|
||||||
@ -417,7 +420,7 @@ u3_cm_bail(u3_noun how)
|
|||||||
{
|
{
|
||||||
/* Printf some metadata.
|
/* Printf some metadata.
|
||||||
*/
|
*/
|
||||||
{
|
if ( c3__exit != how ) {
|
||||||
if ( u3_so(u3ud(how)) ) {
|
if ( u3_so(u3ud(how)) ) {
|
||||||
c3_c str_c[5];
|
c3_c str_c[5];
|
||||||
|
|
||||||
@ -432,12 +435,26 @@ u3_cm_bail(u3_noun how)
|
|||||||
c3_assert(u3_so(u3ud(u3h(how))));
|
c3_assert(u3_so(u3ud(u3h(how))));
|
||||||
|
|
||||||
fprintf(stderr, "bail: %d (at %llu)\r\n", u3h(how), u3N);
|
fprintf(stderr, "bail: %d (at %llu)\r\n", u3h(how), u3N);
|
||||||
u3_cm_p("bail", u3t(how));
|
// u3_cm_p("bail", u3t(how));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// _cm_punt();
|
// _cm_punt();
|
||||||
// u3_lo_sway(2, u3k(u3R->bug.tax));
|
// u3_cm_signal(c3__exit);
|
||||||
abort();
|
|
||||||
|
if ( c3__exit != how ) {
|
||||||
|
u3_lo_sway(2, u3k(u3R->bug.tax));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( &(u3H->rod_u) == u3R ) {
|
||||||
|
// For top-level errors, which shouln't happen often, we have no
|
||||||
|
// choice but to use the signal process; and we require the flat
|
||||||
|
// form of how.
|
||||||
|
//
|
||||||
|
c3_assert(u3_so(u3_co_is_cat(how)));
|
||||||
|
u3_cm_signal(how);
|
||||||
|
}
|
||||||
|
|
||||||
/* Reconstruct a correct error ball.
|
/* Reconstruct a correct error ball.
|
||||||
*/
|
*/
|
||||||
@ -630,17 +647,20 @@ u3_cm_soft_top(c3_w sec_w, // timer seconds
|
|||||||
{
|
{
|
||||||
u3_noun why, pro;
|
u3_noun why, pro;
|
||||||
c3_w gof_w;
|
c3_w gof_w;
|
||||||
|
c3_l sig_l;
|
||||||
|
|
||||||
/* Enter internal signal regime.
|
/* Enter internal signal regime.
|
||||||
*/
|
*/
|
||||||
_cm_signal_deep(0);
|
_cm_signal_deep(0);
|
||||||
|
|
||||||
if ( 0 != sigsetjmp(Signal_u, 1) ) {
|
if ( 0 != (sig_l = sigsetjmp(u3_Signal, 1)) ) {
|
||||||
// return to blank state
|
// return to blank state
|
||||||
//
|
//
|
||||||
_cm_signal_done();
|
_cm_signal_done();
|
||||||
|
|
||||||
return _cm_signal_recover();
|
// recover memory state from the top down
|
||||||
|
//
|
||||||
|
return _cm_signal_recover(sig_l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record the cap, and leap.
|
/* Record the cap, and leap.
|
||||||
@ -701,9 +721,6 @@ u3_cm_soft_run(u3_noun fly,
|
|||||||
u3_noun why, pro;
|
u3_noun why, pro;
|
||||||
c3_w gof_w;
|
c3_w gof_w;
|
||||||
|
|
||||||
u3_cm_wash(aga);
|
|
||||||
u3_cm_wash(agb);
|
|
||||||
|
|
||||||
/* Record the cap, and leap.
|
/* Record the cap, and leap.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
1
g/n.c
1
g/n.c
@ -379,6 +379,7 @@ u3_noun
|
|||||||
u3_cn_nock_an(u3_noun bus, u3_noun fol)
|
u3_cn_nock_an(u3_noun bus, u3_noun fol)
|
||||||
{
|
{
|
||||||
u3_noun fly = u3nt(u3nc(1, 0), 0, 0); // |=(a=* ~)
|
u3_noun fly = u3nt(u3nc(1, 0), 0, 0); // |=(a=* ~)
|
||||||
|
u3_noun pro;
|
||||||
|
|
||||||
return u3_cn_nock_in(fly, bus, fol);
|
return u3_cn_nock_in(fly, bus, fol);
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,11 @@
|
|||||||
u3_noun
|
u3_noun
|
||||||
u3_ca_take(u3_noun som);
|
u3_ca_take(u3_noun som);
|
||||||
|
|
||||||
|
/* u3_ca_audit(): investigate object for bad refcounts.
|
||||||
|
*/
|
||||||
|
c3_o
|
||||||
|
u3_ca_audit(u3_noun som);
|
||||||
|
|
||||||
/* u3_ca_lose(): lose a reference.
|
/* u3_ca_lose(): lose a reference.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
|
@ -18,6 +18,11 @@
|
|||||||
# define u3_cm_trap() (u3_noun)(setjmp(u3R->esc.buf))
|
# define u3_cm_trap() (u3_noun)(setjmp(u3R->esc.buf))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* u3_cm_signal(): treat a nock-level exception as a signal interrupt.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
u3_cm_signal(u3_noun sig_l);
|
||||||
|
|
||||||
/* u3_cm_bail(): bail out. Does not return.
|
/* u3_cm_bail(): bail out. Does not return.
|
||||||
**
|
**
|
||||||
** Bail motes:
|
** Bail motes:
|
||||||
|
@ -144,12 +144,6 @@
|
|||||||
c3_w fre_w; // number of free words
|
c3_w fre_w; // number of free words
|
||||||
} all;
|
} all;
|
||||||
|
|
||||||
struct { // pseudo-interrupt
|
|
||||||
c3_l zap_l; // double signal, very bad
|
|
||||||
c3_l sig_l; // interrupt; written by signal
|
|
||||||
c3_l cry_l; // critical region, or 0
|
|
||||||
} coy;
|
|
||||||
|
|
||||||
struct { // jet dashboard
|
struct { // jet dashboard
|
||||||
u3_ch_root* har_u; // jet index
|
u3_ch_root* har_u; // jet index
|
||||||
} jed;
|
} jed;
|
||||||
@ -160,6 +154,7 @@
|
|||||||
|
|
||||||
struct { // trace stack
|
struct { // trace stack
|
||||||
u3_noun tax; // (list ,*)
|
u3_noun tax; // (list ,*)
|
||||||
|
u3_noun mer; // emergency buffer to release
|
||||||
} bug;
|
} bug;
|
||||||
|
|
||||||
struct { // profile stack
|
struct { // profile stack
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
u3_noun fin = u3t(hoq);
|
u3_noun fin = u3t(hoq);
|
||||||
|
|
||||||
if ( u3_nul == fin ) {
|
if ( u3_nul == fin ) {
|
||||||
|
u3_cm_p("cog", cog);
|
||||||
return u3_cm_error("find-none");
|
return u3_cm_error("find-none");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -332,8 +332,7 @@ int FOO;
|
|||||||
# define _mint_used()
|
# define _mint_used()
|
||||||
|
|
||||||
static u3_noun
|
static u3_noun
|
||||||
_mint_in(
|
_mint_in(u3_noun van,
|
||||||
u3_noun van,
|
|
||||||
u3_noun sut,
|
u3_noun sut,
|
||||||
u3_noun gol,
|
u3_noun gol,
|
||||||
u3_noun gen)
|
u3_noun gen)
|
||||||
@ -388,8 +387,7 @@ int FOO;
|
|||||||
|
|
||||||
if ( u3_yes == u3_cr_sing(rex, gen) ) {
|
if ( u3_yes == u3_cr_sing(rex, gen) ) {
|
||||||
#if 1
|
#if 1
|
||||||
u3_noun zix = u3_cqfu_shep
|
u3_noun zix = u3_cqfu_shep(van, "gene", 'q', u3k(gen));
|
||||||
(van, "gene", 'q', u3k(gen));
|
|
||||||
|
|
||||||
u3_ct_push(u3nc(c3__mean, zix));
|
u3_ct_push(u3nc(c3__mean, zix));
|
||||||
return u3_cm_error("mint-open");
|
return u3_cm_error("mint-open");
|
||||||
@ -422,7 +420,7 @@ int FOO;
|
|||||||
_mint_used();
|
_mint_used();
|
||||||
{
|
{
|
||||||
u3_noun nob = u3_cqfl_bunt(van, p_gen);
|
u3_noun nob = u3_cqfl_bunt(van, p_gen);
|
||||||
u3_noun dok = u3nc(c3__cnzz, q_gen);
|
u3_noun dok = u3nc(c3__cnzz, u3k(q_gen));
|
||||||
u3_noun vol = _mint_corn(van, sut, dok);
|
u3_noun vol = _mint_corn(van, sut, dok);
|
||||||
u3_noun axe = _mint_coke(vol);
|
u3_noun axe = _mint_coke(vol);
|
||||||
u3_noun wam = u3_cqfu_play(van, sut, nob);
|
u3_noun wam = u3_cqfu_play(van, sut, nob);
|
||||||
@ -849,10 +847,7 @@ int FOO;
|
|||||||
u3_noun hum = _mint_in(van, sut, gol, q_gen);
|
u3_noun hum = _mint_in(van, sut, gol, q_gen);
|
||||||
u3_noun bez = u3nt(c3__spot, 1, u3k(p_gen));
|
u3_noun bez = u3nt(c3__spot, 1, u3k(p_gen));
|
||||||
|
|
||||||
ret = u3nc(
|
ret = u3nc(u3k(u3h(hum)), u3nt(10, bez, u3k(u3t(hum))));
|
||||||
u3k(u3h(hum)),
|
|
||||||
u3nt(10, bez, u3k(u3t(hum))));
|
|
||||||
|
|
||||||
u3z(hum);
|
u3z(hum);
|
||||||
}
|
}
|
||||||
u3_ct_drop();
|
u3_ct_drop();
|
||||||
|
Loading…
Reference in New Issue
Block a user