diff options
author | daniel <danieruru@gmail.com> | 2013-01-26 13:10:08 +0900 |
---|---|---|
committer | daniel <danieruru@gmail.com> | 2013-01-26 13:10:08 +0900 |
commit | 35b28230e17a68db48f3b5fc91d2eec0c80e048c (patch) | |
tree | 3682265dbce6a376a9f65835d718515f448a4972 /vxi11_server.c | |
parent | 67801485ab5a9e4509d2bb2cdd9454ee4ed1ab11 (diff) |
Add a "hack" to report back to the vxi11 service code when a link dies.
It's a hack because linux/glibc's RPC implementation doesn't seem to
have the ability to set a recv error callback. The hack is to add an
extra event to the events poll'd.. that event tells us if the socket
died.
Diffstat (limited to 'vxi11_server.c')
-rw-r--r-- | vxi11_server.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/vxi11_server.c b/vxi11_server.c index ae8317f..4185542 100644 --- a/vxi11_server.c +++ b/vxi11_server.c @@ -47,6 +47,7 @@ static gchar* inthandler = NULL; #define LINKLONGSINCEDEADTIMEOUT ((10 * 60) * 1000000) // ten minutes typedef struct { int lid; + int sock; GTimeVal lastactivity; } ActiveLink; @@ -66,6 +67,29 @@ static bool isValidLink(int linkid) { return links[linkid] != NULL; } +static void freelink(ActiveLink* link) { + links[link->lid] = NULL; + globals.Remote.vxi_connections--; +#ifdef DEBUG + printf("link %d destroyed, %d active links\n", link->lid, globals.Remote.vxi_connections); +#endif + g_free(link); +} + +void vxi11_deadsocketcallback(int socket) { + int linkid; + for (linkid = 0; linkid < SIZEOFARRAY(links); linkid++) { + if (links[linkid] != NULL) { + if (links[linkid]->sock == socket) { +#ifdef DEBUG + printf("Freeing link %d, socket died\n", linkid); +#endif + freelink(links[linkid]); + } + } + } +} + // test if a link has expired, this is to avoid dead locks static bool linkexpired(ActiveLink* link) { GTimeVal cutoff; @@ -75,9 +99,7 @@ static bool linkexpired(ActiveLink* link) { #ifdef DEBUG printf("Link %d is apparently dead, removing\n", link->lid); #endif - links[link->lid] = NULL; - g_free(link); - globals.Remote.vxi_connections--; + freelink(link); return true; } else @@ -171,10 +193,11 @@ create_link_1_svc(Create_LinkParms *argp, struct svc_req *rqstp) { } g_assert(linkid != SIZEOFARRAY(links)); link->lid = linkid; + link->sock = rqstp->rq_xprt->xp_sock; touchlink(linkid); globals.Remote.vxi_connections++; #ifdef DEBUG - printf("created link %d, %d active links\n", linkid, globals.Remote.vxi_connections); + printf("created link %d(socket %d), %d active links\n", linkid, link->sock, globals.Remote.vxi_connections); #endif struct sockaddr_in sin; @@ -184,6 +207,7 @@ create_link_1_svc(Create_LinkParms *argp, struct svc_req *rqstp) { result.abortPort = ntohs(sin.sin_port); result.maxRecvSize = MAXRECV; result.lid = linkid; + } } return &result; @@ -468,13 +492,8 @@ destroy_link_1_svc(Device_Link *argp, struct svc_req *rqstp) { unlock(); } - globals.Remote.vxi_connections--; -#ifdef DEBUG - printf("link %d destroyed, %d active links\n", lid, globals.Remote.vxi_connections); -#endif + freelink(links[lid]); result.error = 0; - g_free(links[lid]); - links[lid] = NULL; } return &result; |