Changeset 33b6431b


Ignore:
Timestamp:
May 23, 2011, 10:24:49 PM (13 years ago)
Author:
David Benjamin <davidben@mit.edu>
Branches:
master, release-1.10, release-1.8, release-1.9
Children:
b848e30
Parents:
f97c1a6
git-author:
David Benjamin <davidben@mit.edu> (05/23/11 22:17:05)
git-committer:
David Benjamin <davidben@mit.edu> (05/23/11 22:24:49)
Message:
Clarify owl_io_dispatch ownership

A created owl_io_dispatch is owned by whoever created. For instances
where owl_select needs to remove one of them, we instead invalidate
them. In the case of perl IO dispatches, they are owned by the nebulous
blob that implicitly maps fd to IO dispatch. This is completely insane,
but should avoid leaving people with invalid owl_io_dispatch pointers.

Use this same mechanism to restore owl_select_prune_bad_fds logic.

We really need to kill this and owl_timer in favor of glib's things.
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • owl.h

    rf97c1a6 r33b6431b  
    548548  int fd;                                     /* FD to watch for dispatch. */
    549549  int mode;
     550  bool valid;
    550551  int needs_gc;
    551552  void (*callback)(const struct _owl_io_dispatch *, void *); /* C function to dispatch to. */
  • select.c

    rf97c1a6 r33b6431b  
    125125};
    126126
    127 
    128 static const owl_io_dispatch *owl_select_find_io_dispatch_by_fd(const int fd)
     127/* Returns the valid owl_io_dispatch for a given file descriptor. */
     128static owl_io_dispatch *owl_select_find_valid_io_dispatch_by_fd(const int fd)
    129129{
    130130  int i, len;
     
    135135  for(i = 0; i < len; i++) {
    136136    d = owl_list_get_element(dl, i);
    137     if (d->fd == fd) return d;
     137    if (d->fd == fd && d->valid) return d;
    138138  }
    139139  return NULL;
     
    154154  }
    155155  return -1;
     156}
     157
     158static void owl_select_invalidate_io_dispatch(owl_io_dispatch *d)
     159{
     160  if (d == NULL || !d->valid)
     161    return;
     162  d->valid = false;
     163  g_source_remove_poll(owl_io_dispatch_source, &d->pollfd);
    156164}
    157165
     
    167175        d->needs_gc = 1;
    168176      else {
     177        owl_select_invalidate_io_dispatch(d);
    169178        owl_list_remove_element(dl, elt);
    170179        if (d->destroy)
    171180          d->destroy(d);
    172         g_source_remove_poll(owl_io_dispatch_source, &d->pollfd);
    173181        g_free(d);
    174182      }
     
    195203}
    196204
    197 /* Each FD may have at most one dispatcher.
     205/* Each FD may have at most one valid dispatcher.
    198206 * If a new dispatch is added for an FD, the old one is removed.
    199207 * mode determines what types of events are watched for, and may be any combination of:
     
    204212  owl_io_dispatch *d = g_new(owl_io_dispatch, 1);
    205213  owl_list *dl = owl_global_get_io_dispatch_list(&g);
     214  owl_io_dispatch *other;
    206215
    207216  d->fd = fd;
     217  d->valid = true;
    208218  d->needs_gc = 0;
    209219  d->mode = mode;
     
    224234
    225235
    226   owl_select_remove_io_dispatch(owl_select_find_io_dispatch_by_fd(fd));
     236  other = owl_select_find_valid_io_dispatch_by_fd(fd);
     237  if (other)
     238    owl_select_invalidate_io_dispatch(other);
    227239  owl_list_append_element(dl, d);
    228240
     
    242254  len = owl_list_get_size(dl);
    243255  for(i = 0; i < len; i++) {
    244     const owl_io_dispatch *d = owl_list_get_element(dl, i);
     256    owl_io_dispatch *d = owl_list_get_element(dl, i);
     257    if (!d->valid) continue;
     258    if (d->pollfd.revents & G_IO_NVAL) {
     259      owl_function_debugmsg("Pruning defunct dispatch on fd %d.", d->fd);
     260      owl_select_invalidate_io_dispatch(d);
     261    }
    245262    if (d->pollfd.revents & d->pollfd.events)
    246263      return TRUE;
     
    258275  for (i = 0; i < len; i++) {
    259276    owl_io_dispatch *d = owl_list_get_element(dl, i);
     277    if (!d->valid) continue;
    260278    if ((d->pollfd.revents & d->pollfd.events) && d->callback != NULL) {
    261279      d->callback(d, d->data);
     
    277295int owl_select_add_perl_io_dispatch(int fd, int mode, SV *cb)
    278296{
    279   const owl_io_dispatch *d = owl_select_find_io_dispatch_by_fd(fd);
     297  const owl_io_dispatch *d = owl_select_find_valid_io_dispatch_by_fd(fd);
    280298  if (d != NULL && d->callback != owl_perlconfig_io_dispatch) {
    281299    /* Don't mess with non-perl dispatch functions from here. */
    282300    return 1;
    283301  }
     302  /* Also remove any invalidated perl dispatch functions that may have
     303   * stuck around. */
     304  owl_select_remove_perl_io_dispatch(fd);
    284305  owl_select_add_io_dispatch(fd, mode, owl_perlconfig_io_dispatch, owl_perlconfig_io_dispatch_destroy, cb);
    285306  return 0;
    286307}
    287308
     309static owl_io_dispatch *owl_select_find_perl_io_dispatch(int fd)
     310{
     311  int i, len;
     312  const owl_list *dl;
     313  owl_io_dispatch *d;
     314  dl = owl_global_get_io_dispatch_list(&g);
     315  len = owl_list_get_size(dl);
     316  for(i = 0; i < len; i++) {
     317    d = owl_list_get_element(dl, i);
     318    if (d->fd == fd && d->callback == owl_perlconfig_io_dispatch)
     319      return d;
     320  }
     321  return NULL;
     322}
     323
    288324int owl_select_remove_perl_io_dispatch(int fd)
    289325{
    290   const owl_io_dispatch *d = owl_select_find_io_dispatch_by_fd(fd);
    291   if (d != NULL && d->callback == owl_perlconfig_io_dispatch) {
     326  owl_io_dispatch *d = owl_select_find_perl_io_dispatch(fd);
     327  if (d != NULL) {
    292328    /* Only remove perl io dispatchers from here. */
    293329    owl_select_remove_io_dispatch(d);
     
    320356  }
    321357}
    322 
    323 #if 0
    324 /* FIXME: Reimplement this check in the glib world. */
    325 static void owl_select_prune_bad_fds(void) {
    326   owl_list *dl = owl_global_get_io_dispatch_list(&g);
    327   int len, i;
    328   struct stat st;
    329   owl_io_dispatch *d;
    330 
    331   len = owl_list_get_size(dl);
    332   for (i = 0; i < len; i++) {
    333     d = owl_list_get_element(dl, i);
    334     if (fstat(d->fd, &st) < 0 && errno == EBADF) {
    335       owl_function_debugmsg("Pruning defunct dispatch on fd %d.", d->fd);
    336       d->needs_gc = 1;
    337     }
    338   }
    339   owl_select_io_dispatch_gc();
    340 }
    341 #endif
    342358
    343359typedef struct _owl_task { /*noproto*/
Note: See TracChangeset for help on using the changeset viewer.