Check-in [6af0168ed8]
Overview
Comment:Updated to support unthreaded Tcl and fixed a memory leak with home directory determination
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:6af0168ed827e5774e23d29cc8b9ea61da332cf4
User & Date: rkeene on 2014-11-14 21:46:19
Other Links: manifest | tags
Context
2014-11-15
16:46
Added more debugging, renamed appfs_terminate_interp for with more accurate name, fixed FUSE read/write to use pread/pwrite and return no short reads as is required by FUSE, added call to Tcl_FinalizeThread() on thread termination check-in: d5bfe6710c user: rkeene tags: trunk
2014-11-14
21:46
Updated to support unthreaded Tcl and fixed a memory leak with home directory determination check-in: 6af0168ed8 user: rkeene tags: trunk
21:44
Updated to use TCL_DEFS from tclConfig.sh check-in: 24908ac300 user: rkeene tags: trunk
Changes

Modified appfsd.c from [b7668e46f2] to [1768754e26].

    51     51   /*
    52     52    * Global variables for AppFS caching
    53     53    */
    54     54   pthread_mutex_t appfs_path_info_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
    55     55   int appfs_path_info_cache_size = 8209;
    56     56   struct appfs_pathinfo *appfs_path_info_cache = NULL;
    57     57   
           58  +#ifndef TCL_THREADS
           59  +/*
           60  + * Handle unthreaded Tcl
           61  + */
           62  +pthread_mutex_t appfs_tcl_big_global_lock = PTHREAD_MUTEX_INITIALIZER;
           63  +#define appfs_call_libtcl_enter pthread_mutex_lock(&appfs_tcl_big_global_lock);
           64  +#define appfs_call_libtcl_exit pthread_mutex_unlock(&appfs_tcl_big_global_lock);
           65  +#else
           66  +#define appfs_call_libtcl_enter /**/
           67  +#define appfs_call_libtcl_exit /**/
           68  +#endif
           69  +#define appfs_call_libtcl(x...) appfs_call_libtcl_enter x appfs_call_libtcl_exit
           70  +
    58     71   /*
    59     72    * Global variables for AppFS Tcl Interpreter restarting
    60     73    */
    61     74   int interp_reset_key = 0;
    62     75   
    63     76   /*
    64     77    * AppFS Path Type:  Describes the type of path a given file is
................................................................................
   105    118   
   106    119   /*
   107    120    * Create a new Tcl interpreter and completely initialize it
   108    121    */
   109    122   static Tcl_Interp *appfs_create_TclInterp(char **error_string) {
   110    123   	Tcl_Interp *interp;
   111    124   	int tcl_ret;
          125  +	const char *tcl_setvar_ret;
   112    126   
   113    127   	APPFS_DEBUG("Creating new Tcl interpreter for TID = 0x%llx", (unsigned long long) pthread_self());
   114    128   
          129  +	appfs_call_libtcl(
   115    130   	interp = Tcl_CreateInterp();
          131  +	)
   116    132   	if (interp == NULL) {
   117    133   		fprintf(stderr, "Unable to create Tcl Interpreter.  Aborting.\n");
   118    134   
   119    135   		if (error_string) {
   120    136   			*error_string = strdup("Unable to create Tcl interpreter.");
   121    137   		}
   122    138   
   123    139   		return(NULL);
   124    140   	}
   125    141   
   126         -	Tcl_Preserve(interp);
          142  +	appfs_call_libtcl(Tcl_Preserve(interp);)
   127    143   
          144  +	appfs_call_libtcl(
   128    145   	tcl_ret = Tcl_Init(interp);
          146  +	)
   129    147   	if (tcl_ret != TCL_OK) {
   130    148   		fprintf(stderr, "Unable to initialize Tcl.  Aborting.\n");
          149  +		appfs_call_libtcl(
          150  +			fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          151  +		)
          152  +
          153  +		if (error_string) {
          154  +			appfs_call_libtcl(
          155  +				*error_string = strdup(Tcl_GetStringResult(interp));
          156  +			)
          157  +		}
          158  +
          159  +		appfs_call_libtcl(Tcl_Release(interp);)
          160  +
          161  +		APPFS_DEBUG("Terminating Tcl interpreter.");
          162  +
          163  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
          164  +
          165  +		return(NULL);
          166  +	}
          167  +
          168  +	appfs_call_libtcl(
          169  +		tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]");
          170  +	)
          171  +	if (tcl_ret != TCL_OK) {
          172  +		fprintf(stderr, "Unable to initialize Tcl SHA1.  Aborting.\n");
          173  +		appfs_call_libtcl(
   131    174   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          175  +		)
   132    176   
   133    177   		if (error_string) {
          178  +			appfs_call_libtcl(
   134    179   			*error_string = strdup(Tcl_GetStringResult(interp));
          180  +			)
   135    181   		}
   136    182   
   137         -		Tcl_Release(interp);
          183  +		appfs_call_libtcl(Tcl_Release(interp);)
   138    184   
   139    185   		APPFS_DEBUG("Terminating Tcl interpreter.");
   140    186   
   141         -		Tcl_DeleteInterp(interp);
          187  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   142    188   
   143    189   		return(NULL);
   144    190   	}
   145    191   
   146         -	tcl_ret = Tcl_Eval(interp, "package ifneeded sha1 1.0 [list load {} sha1]");
          192  +	appfs_call_libtcl(
          193  +		tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]");
          194  +	)
   147    195   	if (tcl_ret != TCL_OK) {
   148         -		fprintf(stderr, "Unable to initialize Tcl SHA1.  Aborting.\n");
          196  +		fprintf(stderr, "Unable to initialize Tcl AppFS Package.  Aborting.\n");
          197  +		appfs_call_libtcl(
   149    198   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          199  +		)
   150    200   
   151    201   		if (error_string) {
          202  +			appfs_call_libtcl(
   152    203   			*error_string = strdup(Tcl_GetStringResult(interp));
          204  +			)
   153    205   		}
   154    206   
   155         -		Tcl_Release(interp);
          207  +		appfs_call_libtcl(Tcl_Release(interp);)
   156    208   
   157    209   		APPFS_DEBUG("Terminating Tcl interpreter.");
   158    210   
   159         -		Tcl_DeleteInterp(interp);
   160         -
   161         -		return(NULL);
   162         -	}
   163         -
   164         -	tcl_ret = Tcl_Eval(interp, "package ifneeded appfsd 1.0 [list load {} appfsd]");
   165         -	if (tcl_ret != TCL_OK) {
   166         -		fprintf(stderr, "Unable to initialize Tcl AppFS Package.  Aborting.\n");
   167         -		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
   168         -
   169         -		if (error_string) {
   170         -			*error_string = strdup(Tcl_GetStringResult(interp));
   171         -		}
   172         -
   173         -		Tcl_Release(interp);
   174         -
   175         -		APPFS_DEBUG("Terminating Tcl interpreter.");
   176         -
   177         -		Tcl_DeleteInterp(interp);
          211  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   178    212   
   179    213   		return(NULL);
   180    214   	}
   181    215   
   182    216   	/*
   183    217   	 * Load "pki.tcl" in the same way as appfsd.tcl (see below)
   184    218   	 */
          219  +	appfs_call_libtcl_enter
   185    220   	tcl_ret = Tcl_Eval(interp, ""
   186    221   #include "pki.tcl.h"
   187    222   	"");
          223  +	appfs_call_libtcl_exit
   188    224   	if (tcl_ret != TCL_OK) {
   189    225   		fprintf(stderr, "Unable to initialize Tcl PKI.  Aborting.\n");
          226  +		appfs_call_libtcl(
   190    227   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          228  +		)
   191    229   
   192    230   		if (error_string) {
          231  +			appfs_call_libtcl(
   193    232   			*error_string = strdup(Tcl_GetStringResult(interp));
          233  +			)
   194    234   		}
   195    235   
   196         -		Tcl_Release(interp);
          236  +		appfs_call_libtcl(Tcl_Release(interp);)
   197    237   
   198    238   		APPFS_DEBUG("Terminating Tcl interpreter.");
   199    239   
   200         -		Tcl_DeleteInterp(interp);
          240  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   201    241   
   202    242   		return(NULL);
   203    243   	}
   204    244   
   205    245   	/*
   206    246   	 * Load the "appfsd.tcl" script, which is "compiled" into a C header
   207    247   	 * so that it does not need to exist on the filesystem and can be
   208    248   	 * directly evaluated.
   209    249   	 */
          250  +	appfs_call_libtcl_enter
   210    251   	tcl_ret = Tcl_Eval(interp, ""
   211    252   #include "appfsd.tcl.h"
   212    253   	"");
          254  +	appfs_call_libtcl_exit
   213    255   	if (tcl_ret != TCL_OK) {
   214    256   		fprintf(stderr, "Unable to initialize Tcl AppFS script.  Aborting.\n");
          257  +		appfs_call_libtcl(
   215    258   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          259  +		)
   216    260   
   217    261   		if (error_string) {
          262  +			appfs_call_libtcl(
   218    263   			*error_string = strdup(Tcl_GetStringResult(interp));
          264  +			)
   219    265   		}
   220    266   
   221         -		Tcl_Release(interp);
          267  +		appfs_call_libtcl(Tcl_Release(interp);)
   222    268   
   223    269   		APPFS_DEBUG("Terminating Tcl interpreter.");
   224    270   
   225         -		Tcl_DeleteInterp(interp);
          271  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   226    272   
   227    273   		return(NULL);
   228    274   	}
   229    275   
   230    276   	/*
   231    277   	 * Set global variables from C to Tcl
   232    278   	 */
   233         -	if (Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY) == NULL) {
          279  +	appfs_call_libtcl(
          280  +		tcl_setvar_ret = Tcl_SetVar(interp, "::appfs::cachedir", appfs_cachedir, TCL_GLOBAL_ONLY);
          281  +	)
          282  +	if (tcl_setvar_ret == NULL) {
   234    283   		fprintf(stderr, "Unable to set cache directory.  This should never fail.\n");
   235    284   
   236    285   		if (error_string) {
          286  +			appfs_call_libtcl(
   237    287   			*error_string = strdup(Tcl_GetStringResult(interp));
          288  +			)
   238    289   		}
   239    290   
   240         -		Tcl_Release(interp);
          291  +		appfs_call_libtcl(Tcl_Release(interp);)
   241    292   
   242    293   		APPFS_DEBUG("Terminating Tcl interpreter.");
   243    294   
   244         -		Tcl_DeleteInterp(interp);
          295  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   245    296   
   246    297   		return(NULL);
   247    298   	}
   248    299   
   249    300   	/*
   250    301   	 * Initialize the "appfsd.tcl" environment, which must be done after
   251    302   	 * global variables are set.
   252    303   	 */
          304  +	appfs_call_libtcl(
   253    305   	tcl_ret = Tcl_Eval(interp, "::appfs::init");
          306  +	)
   254    307   	if (tcl_ret != TCL_OK) {
   255    308   		fprintf(stderr, "Unable to initialize Tcl AppFS script (::appfs::init).  Aborting.\n");
          309  +		appfs_call_libtcl(
   256    310   		fprintf(stderr, "Tcl Error is: %s\n", Tcl_GetStringResult(interp));
          311  +		)
   257    312   
   258    313   		if (error_string) {
          314  +			appfs_call_libtcl(
   259    315   			*error_string = strdup(Tcl_GetStringResult(interp));
          316  +			)
   260    317   		}
   261    318   
   262         -		Tcl_Release(interp);
          319  +		appfs_call_libtcl(Tcl_Release(interp);)
   263    320   
   264    321   		APPFS_DEBUG("Terminating Tcl interpreter.");
   265    322   
   266         -		Tcl_DeleteInterp(interp);
          323  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   267    324   
   268    325   		return(NULL);
   269    326   	}
   270    327   
   271    328   	/*
   272    329   	 * Hide some Tcl commands that we do not care to use and which may
   273    330   	 * slow down run-time operations.
   274    331   	 */
          332  +	appfs_call_libtcl(
   275    333   	Tcl_HideCommand(interp, "auto_load_index", "auto_load_index");
   276    334   	Tcl_HideCommand(interp, "unknown", "unknown");
   277    335   	Tcl_HideCommand(interp, "exit", "exit");
          336  +	)
   278    337   
   279    338   	/*
   280    339   	 * Release the hold we have on the interpreter so that it may be
   281    340   	 * deleted if needed
   282    341   	 */
   283         -	Tcl_Release(interp);
          342  +	appfs_call_libtcl(Tcl_Release(interp);)
   284    343   
   285    344   	/*
   286    345   	 * Return the completely initialized interpreter
   287    346   	 */
   288    347   	return(interp);
   289    348   }
   290    349   
................................................................................
   299    358   
   300    359   	global_interp_reset_key = __sync_fetch_and_add(&interp_reset_key, 0);
   301    360   
   302    361   	interp = pthread_getspecific(interpKey);
   303    362   	if (interp != NULL && thread_interp_reset_key != global_interp_reset_key) {
   304    363   		APPFS_DEBUG("Terminating old interpreter and restarting due to reset request.");
   305    364   
   306         -		Tcl_DeleteInterp(interp);
          365  +		appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   307    366   
   308    367   		interp = NULL;
   309    368   
   310    369   		pthread_ret = pthread_setspecific(interpKey, interp);
   311    370   	}
   312    371   
   313    372   	if (global_interp_reset_key == -1) {
................................................................................
   325    384   			return(NULL);
   326    385   		}
   327    386   
   328    387   		pthread_ret = pthread_setspecific(interpKey, interp);
   329    388   		if (pthread_ret != 0) {
   330    389   			APPFS_DEBUG("pthread_setspecific() failed.  Terminating Tcl interpreter.");
   331    390   
   332         -			Tcl_DeleteInterp(interp);
          391  +			appfs_call_libtcl(Tcl_DeleteInterp(interp);)
   333    392   
   334    393   			return(NULL);
   335    394   		}
   336    395   	}
   337    396   
   338    397   	return(interp);
   339    398   }
................................................................................
   351    410   
   352    411   	if (interp == NULL) {
   353    412   		return(TCL_ERROR);
   354    413   	}
   355    414   
   356    415   	objv = (void *) ckalloc(sizeof(*objv) * objc);
   357    416   
          417  +	appfs_call_libtcl(
   358    418   	objv[0] = Tcl_NewStringObj(cmd, -1);
   359    419   
   360    420   	Tcl_IncrRefCount(objv[0]);
   361    421   
   362    422   	va_start(argp, cmd);
   363    423   	for (i = 1; i < objc; i++) {
   364    424   		arg = va_arg(argp, const char *);
   365    425   
   366    426   		objv[i] = Tcl_NewStringObj(arg, -1);
   367    427   
   368    428   		Tcl_IncrRefCount(objv[i]);
   369    429   	}
   370    430   	va_end(argp);
          431  +	)
   371    432   
          433  +	appfs_call_libtcl(
   372    434   	retval = Tcl_EvalObjv(interp, objc, objv, 0);
          435  +	)
   373    436   
          437  +	appfs_call_libtcl(
   374    438   	for (i = 0; i < objc; i++) {
   375    439   		Tcl_DecrRefCount(objv[i]);
   376    440   	}
          441  +	)
   377    442   
   378    443   	ckfree((void *) objv);
   379    444   
   380    445   	if (retval != TCL_OK) {
          446  +		appfs_call_libtcl(
   381    447   		APPFS_DEBUG("Tcl command failed, ::errorInfo contains: %s\n", Tcl_GetVar(interp, "::errorInfo", 0));
          448  +		)
   382    449   	}
   383    450   
   384    451   	return(retval);
   385    452   }
   386    453   
   387    454   /*
   388    455    * Request all Tcl interpreters restart
................................................................................
   696    763   	Tcl_Obj *attrs_dict, *attr_value;
   697    764   	const char *attr_value_str;
   698    765   	Tcl_WideInt attr_value_wide;
   699    766   	int attr_value_int;
   700    767   	static __thread Tcl_Obj *attr_key_type = NULL, *attr_key_perms = NULL, *attr_key_size = NULL, *attr_key_time = NULL, *attr_key_source = NULL, *attr_key_childcount = NULL, *attr_key_packaged = NULL;
   701    768   	int cache_ret;
   702    769   	int tcl_ret;
          770  +	int retval;
   703    771   	uid_t fsuid;
          772  +
          773  +	retval = 0;
   704    774   
   705    775   	fsuid = appfs_get_fsuid();
   706    776   
   707    777   	cache_ret = appfs_get_path_info_cache_get(path, fsuid, pathinfo);
   708    778   	if (cache_ret == 0) {
   709    779   		if (pathinfo->type == APPFS_PATHTYPE_DOES_NOT_EXIST) {
   710    780   			return(-ENOENT);
................................................................................
   718    788   	}
   719    789   
   720    790   	interp = appfs_TclInterp();
   721    791   	if (interp == NULL) {
   722    792   		return(-EIO);
   723    793   	}
   724    794   
   725         -	Tcl_Preserve(interp);
          795  +	appfs_call_libtcl(Tcl_Preserve(interp);)
   726    796   
   727    797   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getattr", path);
   728    798   	if (tcl_ret != TCL_OK) {
   729    799   		APPFS_DEBUG("::appfs::getattr(%s) failed.", path);
          800  +		appfs_call_libtcl(
   730    801   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
          802  +		)
   731    803   
   732    804   		pathinfo->type = APPFS_PATHTYPE_DOES_NOT_EXIST;
   733    805   
   734    806   		appfs_get_path_info_cache_add(path, fsuid, pathinfo);
   735    807   
   736         -		Tcl_Release(interp);
          808  +		appfs_call_libtcl(Tcl_Release(interp);)
   737    809   
   738    810   		return(-ENOENT);
   739    811   	}
   740    812   
   741    813   	if (attr_key_type == NULL) {
          814  +		appfs_call_libtcl(
   742    815   		attr_key_type       = Tcl_NewStringObj("type", -1);
   743    816   		attr_key_perms      = Tcl_NewStringObj("perms", -1);
   744    817   		attr_key_size       = Tcl_NewStringObj("size", -1);
   745    818   		attr_key_time       = Tcl_NewStringObj("time", -1);
   746    819   		attr_key_source     = Tcl_NewStringObj("source", -1);
   747    820   		attr_key_childcount = Tcl_NewStringObj("childcount", -1);
   748    821   		attr_key_packaged   = Tcl_NewStringObj("packaged", -1);
          822  +
          823  +			Tcl_IncrRefCount(attr_key_type);
          824  +			Tcl_IncrRefCount(attr_key_perms);
          825  +			Tcl_IncrRefCount(attr_key_size);
          826  +			Tcl_IncrRefCount(attr_key_time);
          827  +			Tcl_IncrRefCount(attr_key_source);
          828  +			Tcl_IncrRefCount(attr_key_childcount);
          829  +			Tcl_IncrRefCount(attr_key_packaged);
          830  +		)
   749    831   	}
   750    832   
          833  +	appfs_call_libtcl(
   751    834   	attrs_dict = Tcl_GetObjResult(interp);
   752    835   	tcl_ret = Tcl_DictObjGet(interp, attrs_dict, attr_key_type, &attr_value);
          836  +	)
   753    837   	if (tcl_ret != TCL_OK) {
   754    838   		APPFS_DEBUG("[dict get \"type\"] failed");
          839  +		appfs_call_libtcl(
   755    840   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
          841  +		)
   756    842   
   757         -		Tcl_Release(interp);
          843  +		appfs_call_libtcl(Tcl_Release(interp);)
   758    844   
   759    845   		return(-EIO);
   760    846   	}
   761    847   
   762    848   	if (attr_value == NULL) {
   763         -		Tcl_Release(interp);
          849  +		appfs_call_libtcl(Tcl_Release(interp);)
   764    850   
   765    851   		return(-EIO);
   766    852   	}
   767    853   
   768    854   	pathinfo->packaged = 0;
   769    855   	pathinfo->inode = appfs_get_path_inode(path);
   770    856   
          857  +	appfs_call_libtcl(
   771    858   	attr_value_str = Tcl_GetString(attr_value);
   772    859   
   773    860   	switch (attr_value_str[0]) {
   774    861   		case 'd': /* directory */
   775    862   			pathinfo->type = APPFS_PATHTYPE_DIRECTORY;
   776    863   			pathinfo->typeinfo.dir.childcount = 0;
   777    864   
................................................................................
   825    912   		case 'F': /* pipe/fifo */
   826    913   			pathinfo->type = APPFS_PATHTYPE_FIFO;
   827    914   			break;
   828    915   		case 'S': /* UNIX domain socket */
   829    916   			pathinfo->type = APPFS_PATHTYPE_SOCKET;
   830    917   			break;
   831    918   		default:
   832         -			Tcl_Release(interp);
   833         -
   834         -			return(-EIO);
          919  +				retval = -EIO;
   835    920   	}
   836    921   
   837    922   	Tcl_DictObjGet(interp, attrs_dict, attr_key_packaged, &attr_value);
   838    923   	if (attr_value != NULL) {
   839    924   		pathinfo->packaged = 1;
   840    925   	}
   841    926   
................................................................................
   846    931   			pathinfo->time = attr_value_wide;
   847    932   		}
   848    933   	} else {
   849    934   		pathinfo->time = 0;
   850    935   	}
   851    936   
   852    937   	Tcl_Release(interp);
          938  +	)
   853    939   
          940  +	if (retval == 0) {
   854    941   	appfs_get_path_info_cache_add(path, fsuid, pathinfo);
          942  +	}
   855    943   
   856         -	return(0);
          944  +	return(retval);
   857    945   }
   858    946   
   859    947   static char *appfs_prepare_to_create(const char *path) {
   860    948   	Tcl_Interp *interp;
   861    949   	const char *real_path;
   862    950   	int tcl_ret;
   863    951   
................................................................................
   864    952   	appfs_get_path_info_cache_flush(appfs_get_fsuid(), -1);
   865    953   
   866    954   	interp = appfs_TclInterp();
   867    955   	if (interp == NULL) {
   868    956   		return(NULL);
   869    957   	}
   870    958   
   871         -	Tcl_Preserve(interp);
          959  +	appfs_call_libtcl(Tcl_Preserve(interp);)
   872    960   
          961  +	appfs_call_libtcl(
   873    962   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::prepare_to_create", path);
          963  +	)
   874    964   	if (tcl_ret != TCL_OK) {
   875    965   		APPFS_DEBUG("::appfs::prepare_to_create(%s) failed.", path);
          966  +		appfs_call_libtcl(
   876    967   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
          968  +		)
   877    969   
   878         -		Tcl_Release(interp);
          970  +		appfs_call_libtcl(Tcl_Release(interp);)
   879    971   
   880    972   		return(NULL);
   881    973   	}
   882    974   
          975  +	appfs_call_libtcl(
   883    976   	real_path = Tcl_GetStringResult(interp);
          977  +	)
   884    978   
   885         -	Tcl_Release(interp);
          979  +	appfs_call_libtcl(Tcl_Release(interp);)
   886    980   
   887    981   	if (real_path == NULL) {
   888    982   		return(NULL);
   889    983   	}
   890    984   
   891    985   	return(strdup(real_path));
   892    986   }
................................................................................
   897    991   	int tcl_ret;
   898    992   
   899    993   	interp = appfs_TclInterp();
   900    994   	if (interp == NULL) {
   901    995   		return(NULL);
   902    996   	}
   903    997   
   904         -	Tcl_Preserve(interp);
          998  +	appfs_call_libtcl(Tcl_Preserve(interp);)
   905    999   
         1000  +	appfs_call_libtcl(
   906   1001   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::localpath", path);
         1002  +	)
   907   1003   	if (tcl_ret != TCL_OK) {
   908   1004   		APPFS_DEBUG("::appfs::localpath(%s) failed.", path);
         1005  +		appfs_call_libtcl(
   909   1006   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1007  +		)
   910   1008   
   911   1009   		return(NULL);
   912   1010   	}
   913   1011   
         1012  +	appfs_call_libtcl(
   914   1013   	real_path = Tcl_GetStringResult(interp);
         1014  +	)
   915   1015   
   916         -	Tcl_Release(interp);
         1016  +	appfs_call_libtcl(Tcl_Release(interp);)
   917   1017   
   918   1018   	if (real_path == NULL) {
   919   1019   		return(NULL);
   920   1020   	}
   921   1021   
   922   1022   	return(strdup(real_path));
   923   1023   }
................................................................................
  1064   1164   	APPFS_DEBUG("Enter (path = %s, ...)", path);
  1065   1165   
  1066   1166   	interp = appfs_TclInterp();
  1067   1167   	if (interp == NULL) {
  1068   1168   		return(0);
  1069   1169   	}
  1070   1170   
  1071         -	Tcl_Preserve(interp);
         1171  +	appfs_call_libtcl(Tcl_Preserve(interp);)
  1072   1172   
  1073   1173   	filler(buf, ".", NULL, 0);
  1074   1174   	filler(buf, "..", NULL, 0);
  1075   1175   
  1076   1176   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::getchildren", path);
  1077   1177   	if (tcl_ret != TCL_OK) {
  1078   1178   		APPFS_DEBUG("::appfs::getchildren(%s) failed.", path);
         1179  +		appfs_call_libtcl(
  1079   1180   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1181  +		)
  1080   1182   
  1081         -		Tcl_Release(interp);
         1183  +		appfs_call_libtcl(Tcl_Release(interp);)
  1082   1184   
  1083   1185   		return(0);
  1084   1186   	}
  1085   1187   
         1188  +	appfs_call_libtcl(
  1086   1189   	tcl_ret = Tcl_ListObjGetElements(interp, Tcl_GetObjResult(interp), &children_count, &children);
         1190  +	)
  1087   1191   	if (tcl_ret != TCL_OK) {
  1088   1192   		APPFS_DEBUG("Parsing list of children on path %s failed.", path);
         1193  +		appfs_call_libtcl(
  1089   1194   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1195  +		)
  1090   1196   
  1091         -		Tcl_Release(interp);
         1197  +		appfs_call_libtcl(Tcl_Release(interp);)
  1092   1198   
  1093   1199   		return(0);
  1094   1200   	}
  1095   1201   
  1096   1202   	for (idx = 0; idx < children_count; idx++) {
         1203  +		appfs_call_libtcl(
  1097   1204   		filler(buf, Tcl_GetString(children[idx]), NULL, 0);
         1205  +		)
  1098   1206   	}
  1099   1207   
  1100         -	Tcl_Release(interp);
         1208  +	appfs_call_libtcl(Tcl_Release(interp);)
  1101   1209   
  1102   1210   	return(0);
  1103   1211   }
  1104   1212   
  1105   1213   static int appfs_fuse_open(const char *path, struct fuse_file_info *fi) {
  1106   1214   	Tcl_Interp *interp;
  1107   1215   	struct appfs_pathinfo pathinfo;
................................................................................
  1144   1252   	}
  1145   1253   
  1146   1254   	interp = appfs_TclInterp();
  1147   1255   	if (interp == NULL) {
  1148   1256   		return(-EIO);
  1149   1257   	}
  1150   1258   
  1151         -	Tcl_Preserve(interp);
         1259  +	appfs_call_libtcl(Tcl_Preserve(interp);)
  1152   1260   
  1153   1261   	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, mode);
  1154   1262   	if (tcl_ret != TCL_OK) {
  1155   1263   		APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, mode);
         1264  +		appfs_call_libtcl(
  1156   1265   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1266  +		)
  1157   1267   
  1158         -		Tcl_Release(interp);
         1268  +		appfs_call_libtcl(Tcl_Release(interp);)
  1159   1269   
  1160   1270   		return(-EIO);
  1161   1271   	}
  1162   1272   
         1273  +	appfs_call_libtcl(
  1163   1274   	real_path = Tcl_GetStringResult(interp);
         1275  +	)
  1164   1276   
  1165         -	Tcl_Release(interp);
         1277  +	appfs_call_libtcl(Tcl_Release(interp);)
  1166   1278   
  1167   1279   	if (real_path == NULL) {
  1168   1280   		return(-EIO);
  1169   1281   	}
  1170   1282   
  1171   1283   	APPFS_DEBUG("Translated request to open %s to opening %s (mode = \"%s\")", path, real_path, mode);
  1172   1284   
................................................................................
  1338   1450   	if (interp == NULL) {
  1339   1451   		return(-EIO);
  1340   1452   	}
  1341   1453   
  1342   1454   	tcl_ret = appfs_Tcl_Eval(interp, 2, "::appfs::unlinkpath", path);
  1343   1455   	if (tcl_ret != TCL_OK) {
  1344   1456   		APPFS_DEBUG("::appfs::unlinkpath(%s) failed.", path);
         1457  +		appfs_call_libtcl(
  1345   1458   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1459  +		)
  1346   1460   
  1347         -		Tcl_Release(interp);
         1461  +		appfs_call_libtcl(Tcl_Release(interp);)
  1348   1462   
  1349   1463   		return(-EIO);
  1350   1464   	}
  1351   1465   
  1352         -	Tcl_Release(interp);
         1466  +	appfs_call_libtcl(Tcl_Release(interp);)
  1353   1467   
  1354   1468   	return(0);
  1355   1469   }
  1356   1470   
  1357   1471   static int appfs_fuse_mkdir(const char *path, mode_t mode) {
  1358   1472   	char *real_path;
  1359   1473   	int mkdir_ret;
................................................................................
  1392   1506   	appfs_get_path_info_cache_rm(path, appfs_get_fsuid());
  1393   1507   
  1394   1508   	interp = appfs_TclInterp();
  1395   1509   	if (interp == NULL) {
  1396   1510   		return(-EIO);
  1397   1511   	}
  1398   1512   
  1399         -	Tcl_Preserve(interp);
         1513  +	appfs_call_libtcl(Tcl_Preserve(interp);)
  1400   1514   
  1401   1515   	tcl_ret = appfs_Tcl_Eval(interp, 3, "::appfs::openpath", path, "write");
  1402   1516   	if (tcl_ret != TCL_OK) {
  1403   1517   		APPFS_DEBUG("::appfs::openpath(%s, %s) failed.", path, "write");
         1518  +		appfs_call_libtcl(
  1404   1519   		APPFS_DEBUG("Tcl Error is: %s", Tcl_GetStringResult(interp));
         1520  +		)
  1405   1521   
  1406         -		Tcl_Release(interp);
         1522  +		appfs_call_libtcl(Tcl_Release(interp);)
  1407   1523   
  1408   1524   		return(-EIO);
  1409   1525   	}
  1410   1526   
         1527  +	appfs_call_libtcl(
  1411   1528   	real_path = Tcl_GetStringResult(interp);
         1529  +	)
  1412   1530   
  1413         -	Tcl_Release(interp);
         1531  +	appfs_call_libtcl(Tcl_Release(interp);)
  1414   1532   
  1415   1533   	if (real_path == NULL) {
  1416   1534   		return(-EIO);
  1417   1535   	}
  1418   1536   
  1419   1537   	appfs_simulate_user_fs_enter();
  1420   1538   
................................................................................
  1508   1626                   return(TCL_ERROR);
  1509   1627           }
  1510   1628   
  1511   1629   	fsuid = appfs_get_fsuid();
  1512   1630   
  1513   1631   	if (fsuid == last_fsuid && last_homedir_obj != NULL) {
  1514   1632   		homedir_obj = last_homedir_obj;
         1633  +
         1634  +		Tcl_IncrRefCount(homedir_obj);
  1515   1635   	} else {
  1516   1636   		homedir = appfs_get_homedir(appfs_get_fsuid());
  1517   1637   
  1518   1638   		if (homedir == NULL) {
  1519   1639   			return(TCL_ERROR);
  1520   1640   		}
  1521   1641   
  1522   1642   		homedir_obj = Tcl_NewStringObj(homedir, -1);
  1523   1643   
  1524   1644   		free(homedir);
         1645  +
         1646  +		Tcl_IncrRefCount(homedir_obj);
  1525   1647   
  1526   1648   		if (last_homedir_obj != NULL) {
  1527   1649   			Tcl_DecrRefCount(last_homedir_obj);
  1528   1650   		}
  1529   1651   
  1530   1652   		last_homedir_obj = homedir_obj;
  1531   1653   		last_fsuid = fsuid;
  1532   1654   
  1533         -		Tcl_IncrRefCount(last_homedir_obj);
         1655  +		Tcl_IncrRefCount(homedir_obj);
  1534   1656   	}
  1535   1657   
  1536   1658          	Tcl_SetObjResult(interp, homedir_obj);
         1659  +
         1660  +	Tcl_DecrRefCount(homedir_obj);
  1537   1661   
  1538   1662           return(TCL_OK);
  1539   1663   }
  1540   1664   
  1541   1665   static int tcl_appfs_simulate_user_fs_enter(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
  1542   1666   	appfs_simulate_user_fs_enter();
  1543   1667   
................................................................................
  1655   1779   		return;
  1656   1780   	}
  1657   1781   
  1658   1782   	interp = _interp;
  1659   1783   
  1660   1784   	APPFS_DEBUG("Terminating interpreter due to thread termination");
  1661   1785   
         1786  +	appfs_call_libtcl(
  1662   1787   	Tcl_DeleteInterp(interp);
         1788  +	)
  1663   1789   
  1664   1790   	return;
  1665   1791   }
  1666   1792   
  1667   1793   /*
  1668   1794    * FUSE operations structure
  1669   1795    */
................................................................................
  1791   1917   		}
  1792   1918   
  1793   1919   		fprintf(stderr, "Unable to initialize Tcl interpreter for AppFSd:\n");
  1794   1920   		fprintf(stderr, "%s\n", test_interp_error);
  1795   1921   
  1796   1922   		return(1);
  1797   1923   	}
         1924  +
  1798   1925   	Tcl_DeleteInterp(test_interp);
         1926  +
  1799   1927   	Tcl_FinalizeNotifier(NULL);
  1800   1928   
  1801   1929   	/*
  1802   1930   	 * Register a signal handler for hot-restart requests
  1803   1931   	 */
  1804   1932   	signal_ret = signal(SIGHUP, appfs_signal_handler);
  1805   1933   	if (signal_ret == SIG_ERR) {