diff options
-rw-r--r-- | vxi11_server.c | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/vxi11_server.c b/vxi11_server.c index ed529f2..bf57547 100644 --- a/vxi11_server.c +++ b/vxi11_server.c @@ -44,12 +44,18 @@ static CLIENT* intclient = NULL; static bool intenabled = false; static gchar* inthandler = NULL; +#define LINKLONGSINCEDEADTIMEOUT ((10 * 60) * 1000000) // ten minutes typedef struct { int lid; + GTimeVal lastactivity; } ActiveLink; static ActiveLink* links[MAX_SESSIONS] = { NULL }; +static void touchlink(int lid) { + g_get_current_time(&(links[lid]->lastactivity)); +} + static bool isValidLink(int linkid) { if (linkid > MAX_SESSIONS - 1) { #ifdef DEBUG @@ -60,8 +66,31 @@ static bool isValidLink(int linkid) { return links[linkid] != NULL; } +// test if a link has expired, this is to avoid dead locks +static bool linkexpired(ActiveLink* link) { + GTimeVal cutoff; + g_get_current_time(&cutoff); + g_time_val_add(&cutoff, -LINKLONGSINCEDEADTIMEOUT); + if (link->lastactivity.tv_sec < cutoff.tv_sec) { +#ifdef DEBUG + printf("Link %d is apparently dead, removing\n", link->lid); +#endif + links[link->lid] = NULL; + g_free(link); + globals.Remote.vxi_connections--; + return true; + } + else + return false; +} + static bool isLocked() { - return globals.VxiLocks.locked_network_server != NO_SERVER_LOCKED; + if (globals.VxiLocks.locked_network_server == NO_SERVER_LOCKED) + return false; + else { + ActiveLink* link = links[globals.VxiLocks.locked_network_server]; + return !(linkexpired(link)); + } } static bool haveLock(int lid) { @@ -133,6 +162,8 @@ create_link_1_svc(Create_LinkParms *argp, struct svc_req *rqstp) { else { int linkid; for (linkid = 0; linkid < SIZEOFARRAY(links); linkid++) { + if (links[linkid] != NULL) // clean up any dead links + linkexpired(links[linkid]); if (links[linkid] == NULL) { links[linkid] = link; break; @@ -140,7 +171,7 @@ create_link_1_svc(Create_LinkParms *argp, struct svc_req *rqstp) { } g_assert(linkid != SIZEOFARRAY(links)); link->lid = linkid; - + touchlink(linkid); globals.Remote.vxi_connections++; #ifdef DEBUG printf("created link %d, %d active links\n", linkid, globals.Remote.vxi_connections); @@ -172,6 +203,7 @@ device_write_1_svc(Device_WriteParms *argp, struct svc_req *rqstp) { else if (!waitforio(argp->io_timeout)) result.error = ERR_IOTIMEOUT; else { + touchlink(argp->lid); #ifdef DEBUG printf("got %s on link %d\n", argp->data.data_val, (int) argp->lid); #endif @@ -203,6 +235,7 @@ device_read_1_svc(Device_ReadParms *argp, struct svc_req *rqstp) { result.error = ERR_IOTIMEOUT; } else { + touchlink(argp->lid); if (globals.Registers.pending_output_message != NULL) { result.data.data_len = strlen(globals.Registers.pending_output_message) + 1; result.data.data_val = globals.Registers.pending_output_message; @@ -230,9 +263,10 @@ device_readstb_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { result.error = ERR_INVALIDLINKINDENTIFIER; else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) result.error = ERR_DEVICELOCKEDBYANOTHERLINK; - else + else { + touchlink(argp->lid); result.stb = GPIB_and_VXI_get_STB(); - + } return &result; } @@ -247,6 +281,7 @@ device_trigger_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) result.error = ERR_DEVICELOCKEDBYANOTHERLINK; else { + touchlink(argp->lid); result.error = 0; } return &result; @@ -263,6 +298,7 @@ device_clear_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) result.error = ERR_DEVICELOCKEDBYANOTHERLINK; else { + touchlink(argp->lid); result.error = 0; } return &result; @@ -281,8 +317,10 @@ device_remote_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { else { if (isLocked() && !haveLock(argp->lid)) result.error = ERR_DEVICELOCKEDBYANOTHERLINK; - else + else { + touchlink(argp->lid); result.error = 0; + } } return &result; } @@ -300,8 +338,10 @@ device_local_1_svc(Device_GenericParms *argp, struct svc_req *rqstp) { else { if (isLocked() && !haveLock(argp->lid)) result.error = ERR_DEVICELOCKEDBYANOTHERLINK; - else + else { + touchlink(argp->lid); result.error = 0; + } } return &result; } @@ -322,6 +362,7 @@ device_lock_1_svc(Device_LockParms *argp, struct svc_req *rqstp) { } } else { + touchlink(argp->lid); lock(argp->lid); result.error = 0; } @@ -341,6 +382,7 @@ device_unlock_1_svc(Device_Link *argp, struct svc_req *rqstp) { if (!isLocked(*argp) || !haveLock(*argp)) result.error = ERR_NOLOCKHELDBYTHISLINK; else { + touchlink(*argp); result.error = 0; unlock(); } @@ -366,6 +408,7 @@ device_enable_srq_1_svc(Device_EnableSrqParms *argp, struct svc_req *rqstp) { if (!isValidLink(argp->lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { + touchlink(argp->lid); if (inthandler != NULL) { g_free(inthandler); inthandler = NULL; @@ -395,6 +438,7 @@ device_docmd_1_svc(Device_DocmdParms *argp, struct svc_req *rqstp) { else if (isLocked() && !haveLock(argp->lid) && !waitForLock(argp->flags, argp->lock_timeout)) result.error = ERR_DEVICELOCKEDBYANOTHERLINK; else { + touchlink(argp->lid); result.data_out.data_out_len = 0; result.data_out.data_out_val = NULL; result.error = ERR_OPERATIONNOTSUPPORTED; @@ -412,7 +456,6 @@ destroy_link_1_svc(Device_Link *argp, struct svc_req *rqstp) { if (!isValidLink(lid)) result.error = ERR_INVALIDLINKINDENTIFIER; else { - if (haveLock(*argp)) { #ifdef DEBUG printf("Disconnecting client was holding a lock, freeing it\n"); |