From: Zoran V. <vas...@us...> - 2005-02-17 09:43:47
|
Update of /cvsroot/naviserver/naviserver/nsd In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv22906/nsd Modified Files: tclfile.c Log Message: Fixed broken NsTclChanObjCmd command which caused server crashes when trasporting channels between threads when linked against Tcl 8.4+ Index: tclfile.c =================================================================== RCS file: /cvsroot/naviserver/naviserver/nsd/tclfile.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** tclfile.c 16 Feb 2005 08:39:58 -0000 1.1.1.1 --- tclfile.c 17 Feb 2005 09:43:39 -0000 1.2 *************** *** 1,7 **** /* ! * The contents of this file are subject to the AOLserver Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at ! * http://aolserver.com/. * * Software distributed under the License is distributed on an "AS IS" --- 1,7 ---- /* ! * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at ! * http://mozilla.org/. * * Software distributed under the License is distributed on an "AS IS" *************** *** 44,47 **** --- 44,56 ---- #endif + /* + * Structure handling one registered channel for the [ns_chan] command + */ + + typedef struct _NsRegChan { + char *name; + Tcl_Channel chan; + } NsRegChan; + static void SpliceChannel(Tcl_Interp *interp, Tcl_Channel chan); static void UnspliceChannel(Tcl_Interp *interp, Tcl_Channel chan); *************** *** 1017,1021 **** NsServer *servPtr = itPtr->servPtr; Tcl_Channel chan = NULL; ! char *name; int new, shared; Tcl_HashTable *tabPtr; --- 1026,1031 ---- NsServer *servPtr = itPtr->servPtr; Tcl_Channel chan = NULL; ! char *name, *chanName; ! NsRegChan *regChan = NULL; int new, shared; Tcl_HashTable *tabPtr; *************** *** 1041,1066 **** case CCreateIdx: if (objc != 4) { ! Tcl_WrongNumArgs(interp, 1, objv, "create channel name"); return TCL_ERROR; } ! chan = Tcl_GetChannel(interp, Tcl_GetString(objv[2]), NULL); if (chan == (Tcl_Channel)NULL) { return TCL_ERROR; } - if (!Tcl_IsChannelRegistered(interp, chan)) { - Tcl_SetResult(interp, "channel is not registered", TCL_STATIC); - return TCL_ERROR; - } if (Tcl_IsChannelShared(chan)) { Tcl_SetResult(interp, "channel is shared", TCL_STATIC); return TCL_ERROR; } ! name = Tcl_GetString(objv[3]); ! Ns_MutexLock(&servPtr->chans.lock); hPtr = Tcl_CreateHashEntry(&servPtr->chans.table, name, &new); ! if (new) { ! Tcl_SetHashValue(hPtr, chan); ! } ! Ns_MutexUnlock(&servPtr->chans.lock); if (!new) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), --- 1051,1077 ---- case CCreateIdx: if (objc != 4) { ! Tcl_WrongNumArgs(interp, 1, objv, "create channel name"); return TCL_ERROR; } ! chanName = Tcl_GetString(objv[2]); ! chan = Tcl_GetChannel(interp, chanName, NULL); if (chan == (Tcl_Channel)NULL) { return TCL_ERROR; } if (Tcl_IsChannelShared(chan)) { Tcl_SetResult(interp, "channel is shared", TCL_STATIC); return TCL_ERROR; } ! name = Tcl_GetString(objv[3]); ! Ns_MutexLock(&servPtr->chans.lock); hPtr = Tcl_CreateHashEntry(&servPtr->chans.table, name, &new); ! if (new) { ! regChan = Ns_Malloc(sizeof(NsRegChan)); ! regChan->name = Ns_Malloc(strlen(chanName)+1); ! regChan->chan = chan; ! strcpy(regChan->name, chanName); ! Tcl_SetHashValue(hPtr, regChan); ! } ! Ns_MutexUnlock(&servPtr->chans.lock); if (!new) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), *************** *** 1070,1074 **** } UnspliceChannel(interp, chan); ! break; case CGetIdx: --- 1081,1085 ---- } UnspliceChannel(interp, chan); ! break; case CGetIdx: *************** *** 1078,1087 **** } name = Tcl_GetString(objv[2]); ! Ns_MutexLock(&servPtr->chans.lock); ! hPtr = Tcl_FindHashEntry(&servPtr->chans.table, name); if (hPtr != NULL) { ! chan = (Tcl_Channel)Tcl_GetHashValue(hPtr); Tcl_DeleteHashEntry(hPtr); ! } Ns_MutexUnlock(&servPtr->chans.lock); if (hPtr == NULL) { --- 1089,1098 ---- } name = Tcl_GetString(objv[2]); ! Ns_MutexLock(&servPtr->chans.lock); ! hPtr = Tcl_FindHashEntry(&servPtr->chans.table, name); if (hPtr != NULL) { ! regChan = (NsRegChan*)Tcl_GetHashValue(hPtr); Tcl_DeleteHashEntry(hPtr); ! } Ns_MutexUnlock(&servPtr->chans.lock); if (hPtr == NULL) { *************** *** 1090,1097 **** return TCL_ERROR; } ! SpliceChannel(interp, chan); ! Tcl_SetResult(interp, (char*)Tcl_GetChannelName(chan), TCL_VOLATILE); hPtr = Tcl_CreateHashEntry(&itPtr->chans, name, &new); ! Tcl_SetHashValue(hPtr, chan); break; --- 1101,1108 ---- return TCL_ERROR; } ! SpliceChannel(interp, regChan->chan); ! Tcl_SetResult(interp, regChan->name, TCL_VOLATILE); hPtr = Tcl_CreateHashEntry(&itPtr->chans, name, &new); ! Tcl_SetHashValue(hPtr, regChan); break; *************** *** 1105,1118 **** if (hPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), ! "no such shared channel: ", name, NULL); return TCL_ERROR; } ! chan = Tcl_GetHashValue(hPtr); ! UnspliceChannel(interp, chan); Tcl_DeleteHashEntry(hPtr); ! Ns_MutexLock(&servPtr->chans.lock); hPtr = Tcl_CreateHashEntry(&servPtr->chans.table, name, &new); ! Tcl_SetHashValue(hPtr, chan); ! Ns_MutexUnlock(&servPtr->chans.lock); break; --- 1116,1137 ---- if (hPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), ! "no such shared channel: ", name, NULL); return TCL_ERROR; } ! regChan = (NsRegChan*)Tcl_GetHashValue(hPtr); ! chan = Tcl_GetChannel(interp, regChan->name, NULL); ! if (chan == (Tcl_Channel)NULL || chan != regChan->chan) { ! Tcl_DeleteHashEntry(hPtr); ! if (chan != regChan->chan) { ! Tcl_SetResult(interp, "channel mismatch", TCL_STATIC); ! } ! return TCL_ERROR; ! } ! UnspliceChannel(interp, regChan->chan); Tcl_DeleteHashEntry(hPtr); ! Ns_MutexLock(&servPtr->chans.lock); hPtr = Tcl_CreateHashEntry(&servPtr->chans.table, name, &new); ! Tcl_SetHashValue(hPtr, regChan); ! Ns_MutexUnlock(&servPtr->chans.lock); break; *************** *** 1122,1126 **** return TCL_ERROR; } ! shared = (objc == 3); if (shared) { Ns_MutexLock(&servPtr->chans.lock); --- 1141,1145 ---- return TCL_ERROR; } ! shared = (objc == 3); if (shared) { Ns_MutexLock(&servPtr->chans.lock); *************** *** 1144,1151 **** return TCL_ERROR; } ! shared = (objc == 3); if (shared) { Ns_MutexLock(&servPtr->chans.lock); ! tabPtr = &servPtr->chans.table; } else { tabPtr = &itPtr->chans; --- 1163,1170 ---- return TCL_ERROR; } ! shared = (objc == 3); if (shared) { Ns_MutexLock(&servPtr->chans.lock); ! tabPtr = &servPtr->chans.table; } else { tabPtr = &itPtr->chans; *************** *** 1153,1164 **** hPtr = Tcl_FirstHashEntry(tabPtr, &search); while (hPtr != NULL) { ! chan = Tcl_GetHashValue(hPtr); if (shared) { ! Tcl_Close(NULL, chan); } Tcl_DeleteHashEntry(hPtr); hPtr = Tcl_NextHashEntry(&search); } ! if (objc == 3) { Ns_MutexUnlock(&servPtr->chans.lock); } --- 1172,1188 ---- hPtr = Tcl_FirstHashEntry(tabPtr, &search); while (hPtr != NULL) { ! regChan = (NsRegChan*)Tcl_GetHashValue(hPtr); if (shared) { ! Tcl_SpliceChannel(regChan->chan); ! Tcl_UnregisterChannel((Tcl_Interp*)NULL, regChan->chan); ! } else { ! Tcl_UnregisterChannel(interp, regChan->chan); } + Ns_Free(regChan->name); + Ns_Free(regChan); Tcl_DeleteHashEntry(hPtr); hPtr = Tcl_NextHashEntry(&search); } ! if (shared) { Ns_MutexUnlock(&servPtr->chans.lock); } |