summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordaniel <danieruru@gmail.com>2013-01-25 00:20:30 +0900
committerdaniel <danieruru@gmail.com>2013-01-25 00:20:30 +0900
commitd30320dd62ae86da9d1aa8fe61066aa51bc0e102 (patch)
tree3dfa910673b5833be46290ddb26b10b5331c43a6
parent5ca38c3d82fdca7be88787b951c832789c9b904e (diff)
Add some code to track when a link was last active and some code in create link and the lock
check to see if a link hasn't been active for a long time and if so remove it. This should make deadlocks less of a problem.. before if a link held the lock and then disappeared no one else would ever be able to lock again. If 8 clients connected and didn't shutdown their link no more clients would be able to connect.
-rw-r--r--vxi11_server.c57
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");