From: Willy Tarreau Date: Fri, 2 Jul 2010 09:18:03 +0000 (+0200) Subject: [MEDIUM] stream-interface: add a ->release callback X-Git-Tag: v1.5-dev8~545 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0bd05eaf2437580e1dee917706ec87aa4ed9b018;p=thirdparty%2Fhaproxy.git [MEDIUM] stream-interface: add a ->release callback When a connection is closed on a stream interface, some iohandlers will need to be informed in order to release some resources. This normally happens upon a shutr+shutw. It is the equivalent of the fd_delete() call which is done for real sockets, except that this time we release internal resources. It can also be used with real sockets because it does not cost anything else and might one day be useful. --- diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h index db166c9b24..cfba687351 100644 --- a/include/types/stream_interface.h +++ b/include/types/stream_interface.h @@ -100,6 +100,7 @@ struct stream_interface { void (*chk_snd)(struct stream_interface *);/* chk_snd function */ int (*connect)(struct stream_interface *, struct proxy *, struct server *, struct sockaddr *, struct sockaddr *); /* connect function if any */ + void (*release)(struct stream_interface *); /* handler to call after the last close() */ void (*iohandler)(struct stream_interface *); /* internal I/O handler when embedded */ struct buffer *ib, *ob; /* input and output buffers */ int conn_retries; /* number of connect retries left */ diff --git a/src/session.c b/src/session.c index 556fffefcb..10c7f13d61 100644 --- a/src/session.c +++ b/src/session.c @@ -139,6 +139,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) s->si[0].err_loc = NULL; s->si[0].connect = NULL; s->si[0].iohandler = NULL; + s->si[0].release = NULL; s->si[0].exp = TICK_ETERNITY; s->si[0].flags = SI_FL_NONE; @@ -161,6 +162,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) s->si[1].err_loc = NULL; s->si[1].connect = NULL; s->si[1].iohandler = NULL; + s->si[1].release = NULL; s->si[1].shutr = stream_int_shutr; s->si[1].shutw = stream_int_shutw; s->si[1].exp = TICK_ETERNITY; @@ -434,6 +436,9 @@ int sess_update_st_con_tcp(struct session *s, struct stream_interface *si) si->flags &= ~SI_FL_CAP_SPLICE; fd_delete(si->fd); + if (si->release) + si->release(si); + if (si->err_type) return 0; diff --git a/src/stream_interface.c b/src/stream_interface.c index c45abdbe82..113f01c65d 100644 --- a/src/stream_interface.c +++ b/src/stream_interface.c @@ -178,6 +178,9 @@ void stream_int_shutr(struct stream_interface *si) si->exp = TICK_ETERNITY; } + if (si->release) + si->release(si); + /* note that if the task exist, it must unregister itself once it runs */ if (!(si->flags & SI_FL_DONT_WAKE) && si->owner) task_wakeup(si->owner, TASK_WOKEN_IO); @@ -214,6 +217,9 @@ void stream_int_shutw(struct stream_interface *si) si->exp = TICK_ETERNITY; } + if (si->release) + si->release(si); + /* note that if the task exist, it must unregister itself once it runs */ if (!(si->flags & SI_FL_DONT_WAKE) && si->owner) task_wakeup(si->owner, TASK_WOKEN_IO); @@ -289,6 +295,7 @@ struct task *stream_int_register_handler(struct stream_interface *si, si->chk_snd = stream_int_chk_snd; si->connect = NULL; si->iohandler = fct; + si->release = NULL; si->flags |= SI_FL_WAIT_DATA; return si->owner; } @@ -312,6 +319,7 @@ struct task *stream_int_register_handler_task(struct stream_interface *si, si->chk_snd = stream_int_chk_snd; si->connect = NULL; si->iohandler = NULL; /* not used when running as an external task */ + si->release = NULL; si->flags |= SI_FL_WAIT_DATA; t = task_new(); @@ -337,6 +345,7 @@ void stream_int_unregister_handler(struct stream_interface *si) task_free(si->owner); } si->iohandler = NULL; + si->release = NULL; si->owner = NULL; } diff --git a/src/stream_sock.c b/src/stream_sock.c index 2d5ef6d704..8cd721ea7e 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -875,6 +875,9 @@ void stream_sock_shutw(struct stream_interface *si) si->exp = TICK_ETERNITY; return; } + + if (si->release) + si->release(si); } /* @@ -899,6 +902,9 @@ void stream_sock_shutr(struct stream_interface *si) fd_delete(si->fd); si->state = SI_ST_DIS; si->exp = TICK_ETERNITY; + + if (si->release) + si->release(si); return; } EV_FD_CLR(si->fd, DIR_RD);