Commit a9efce68 authored by Maria Matejka's avatar Maria Matejka
Browse files

Fixed a race condition in channel aux table cleanup

parent 4f43d326
Loading
Loading
Loading
Loading
+32 −8
Original line number Original line Diff line number Diff line
@@ -667,9 +667,14 @@ static void
channel_aux_stopped(void *data)
channel_aux_stopped(void *data)
{
{
  struct channel_aux_table *cat;
  struct channel_aux_table *cat;

  RT_LOCKED((rtable *) data, t)
  RT_LOCKED((rtable *) data, t)
    cat = t->config->owner;
    cat = t->config->owner;


  ASSERT_DIE(cat->push.hook == NULL);
  ASSERT_DIE(cat->get.hook == NULL);
  ASSERT_DIE(cat->stop_pending);

  struct channel *c = cat->c;
  struct channel *c = cat->c;


  if (channel_aux_imex(cat))
  if (channel_aux_imex(cat))
@@ -685,7 +690,15 @@ static void
channel_aux_import_stopped(void *_cat)
channel_aux_import_stopped(void *_cat)
{
{
  struct channel_aux_table *cat = _cat;
  struct channel_aux_table *cat = _cat;

  cat->push.hook = NULL;
  cat->push.hook = NULL;

  if (!cat->get.hook)
    RT_LOCKED(cat->tab, t)
    {
      t->delete = channel_aux_stopped;
      rt_unlock_table(t);
    }
}
}


static void
static void
@@ -694,23 +707,31 @@ channel_aux_export_stopped(struct rt_export_request *req)
  struct channel_aux_table *cat = SKIP_BACK(struct channel_aux_table, get, req);
  struct channel_aux_table *cat = SKIP_BACK(struct channel_aux_table, get, req);
  req->hook = NULL;
  req->hook = NULL;


  int del;
  if (cat->refeed_pending && !cat->stop_pending)
  RT_LOCKED(cat->tab, t)
  {
    del = !!t->delete;
    cat->refeed_pending = 0;
    rt_request_export(cat->tab, req);


  if (del)
    return;
    return;
  }


  ASSERT_DIE(cat->refeed_pending);
  if (!cat->push.hook)
  cat->refeed_pending = 0;
    RT_LOCKED(cat->tab, t)
  rt_request_export(cat->tab, req);
    {
      t->delete = channel_aux_stopped;
      rt_unlock_table(t);
    }
}
}


static void
static void
channel_aux_stop(struct channel_aux_table *cat)
channel_aux_stop(struct channel_aux_table *cat)
{
{
  ASSERT_DIE(!cat->stop_pending);

  cat->stop_pending = 1;

  RT_LOCKED(cat->tab, t)
  RT_LOCKED(cat->tab, t)
    t->delete = channel_aux_stopped;
    rt_lock_table(t);


  cat->push_stopped = (event) {
  cat->push_stopped = (event) {
    .hook = channel_aux_import_stopped,
    .hook = channel_aux_import_stopped,
@@ -966,6 +987,9 @@ channel_setup_out_table(struct channel *c)
static void
static void
channel_aux_request_refeed(struct channel_aux_table *cat)
channel_aux_request_refeed(struct channel_aux_table *cat)
{
{
  if (cat->stop_pending)
    return;

  cat->refeed_pending = 1;
  cat->refeed_pending = 1;
  rt_stop_export(&cat->get, channel_aux_export_stopped);
  rt_stop_export(&cat->get, channel_aux_export_stopped);
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -572,6 +572,7 @@ struct channel_aux_table {
  rtable *tab;
  rtable *tab;
  event *stop;
  event *stop;
  u8 refeed_pending;
  u8 refeed_pending;
  u8 stop_pending;
};
};


/*
/*