From: <da...@de...> - 2003-06-26 10:56:52
|
"Donal K. Fellows" <don...@ma...> writes: > "David N. Welton" wrote: > > As best I can understand it, if the other code happens to use > > regular stat, it's a problem, because there is a mismatch between > > the structs, and the functions. I.e. Tcl has been compiled with a > > stat64 struct, and you pass that memory location to regular stat, > > and the struct is not filled in correctly. I'm not sure that's > > exactly what the details are, but I know that when I get a > > mismatch, bad things happen. > > Does that make sense? > Sort of, but not quite. I still don't see how the two can actually > be incompatible with each other since stat and stat64 are different > structures and syscalls. (If we used LARGEFILE instead of > LARGEFILE64, I'd admit to a definite problem, but I purposefully > don't do that so as to avoid this sort of problem.) > Note that I did take care to keep old functions that used 'struct > stat' still using that so that binary compatability is maintained. > (I copy across the fields, or throw the correct error if the values > are not copyable.) You should only encounter the new structure with > the new APIs. But if you're trying to cast a 'struct stat' to a > 'Tcl_StatBuf'[*] then you're asking for trouble. I have code that uses the old API's... not Tcl_StatBuf. Let's see if this makes it clearer: #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <dlfcn.h> struct teststruct { int a; struct stat b; int c; }; int main() { void *handle; int (*tclstat)(); struct teststruct ts1; char *error; ts1.a = 1; ts1.c = 1; handle = dlopen("./statmodule.so", RTLD_NOW); if (!handle) { fputs (dlerror(), stderr); exit(1); } tclstat = dlsym(handle, "tclstat"); if ((error = dlerror()) != NULL) { fprintf (stderr, "%s\n", error); exit(1); } (*tclstat)(); if (stat("statproblem.c", &(ts1.b)) != 0) { perror("poof"); } printf("roger that\n"); } Compile with: gcc -g -o statproblem statproblem.c -ldl -lpthread #include <tcl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> struct modteststruct { int a; struct stat b; int c; }; int tclstat() { struct modteststruct ts2; Tcl_Interp *interp; ts2.a = 1; ts2.c = 1; Tcl_FindExecutable(NULL); interp = Tcl_CreateInterp(); Tcl_Init(interp); Tcl_Eval(interp, "puts helloworld"); Tcl_Stat("statproblem.c", &(ts2.b)); Tcl_Finalize(); } Compile with: gcc -g -o statmodule.so -shared statmodule.c -ltcl8.4 gdb ./statproblem ... 24 Tcl_Stat("statproblem.c", &(ts2.b)); (gdb) print ts2 $1 = {a = 1, b = {st_dev = 0, __pad1 = 0, st_ino = 0, st_mode = 2147482496, st_nlink = 0, st_uid = 268293624, st_gid = 0, st_rdev = 9223367089052450816, __pad2 = 0, st_size = 2147482908, st_blksize = 2147482804, st_blocks = 2147482784, st_atime = 267962464, __unused1 = 2147482560, st_mtime = 2147482528, __unused2 = 267868284, st_ctime = 570426468, __unused3 = 268437120, __unused4 = 266283416, __unused5 = 268504320}, c = 1} main () at statproblem.c:38 38 if (stat("statproblem.c", &(ts1.b)) != 0) { (gdb) 41 printf("roger that\n"); (gdb) print ts1 $2 = {a = 1, b = {st_dev = 780, __pad1 = 0, st_ino = 692968, st_mode = 33204, st_nlink = 1, st_uid = 1000, st_gid = 1000, st_rdev = 0, __pad2 = 0, st_size = 683, st_blksize = 4096, st_blocks = 8, st_atime = 1056624380, __unused1 = 0, st_mtime = 1056621900, __unused2 = 0, st_ctime = 1056621900, __unused3 = 0, __unused4 = 0, __unused5 = 0}, c = 1} *Something* there is not working. In this case, it's manifesting itself in the results of Tcl_Stat. More information: @ashland [~/tmp] $ objdump -T statproblem | grep stat statproblem: file format elf32-powerpc 10010bb0 DF *UND* 000000cc GLIBC_2.0 __xstat @ashland [~/tmp] $ objdump -T statmodule.so | grep stat statmodule.so: file format elf32-powerpc 00001998 g DF .text 00000088 Base tclstat @ashland [~/tmp] $ objdump -T /usr/lib/libtcl8.4.so | grep stat 00000000 DF *UND* 00000024 GLIBC_2.0 pthread_attr_setdetachstate 0009ab24 g DF .text 00000044 Base TclpObjLstat 0006c480 g DF .text 00000080 Base Tcl_FSLstat 00000000 DF *UND* 00000110 GLIBC_2.2 __xstat64 00000000 DF *UND* 00000110 GLIBC_2.2 __lxstat64 000c9134 g DO .sbss 00000004 Base TclDatestate Furthermore, things work fine if the module is like this: int tclstat() { struct modteststruct ts2; ts2.a = 1; ts2.c = 1; stat("statproblem.c", &(ts2.b)); printf("module done\n"); } with no tcl link or includes. So, while I unfortunately don't have any answers, at least maybe the problem is clearer now? -- David N. Welton Consulting: http://www.dedasys.com/ Personal: http://www.dedasys.com/davidw/ Free Software: http://www.dedasys.com/freesoftware/ Apache Tcl: http://tcl.apache.org/ |