Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | more extensive fix for [76f47e0376fb] and similar errors (additionally avoid segfault if string representation would be broken, e. g. without NTS 0-byte). |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | thread-2-8-branch |
Files: | files | file ages | folders |
SHA3-256: |
98170da1657fb2dce547bd1d21526274 |
User & Date: | sebres 2018-07-17 09:54:36.268 |
References
2018-07-17
| ||
11:12 | • Ticket [76f47e0376] thread::send -async script varname aborts with "alloc: invalid block" status still Closed with 5 other changes artifact: 8ba9148366 user: pooryorick | |
Context
2018-07-17
| ||
10:23 | test-cases extended check-in: 1765cdf3c9 user: sebres tags: thread-2-8-branch | |
09:59 | merge 2.8 check-in: b925b34699 user: sebres tags: trunk | |
09:54 | more extensive fix for [76f47e0376fb] and similar errors (additionally avoid segfault if string representation would be broken, e. g. without NTS 0-byte). check-in: 98170da165 user: sebres tags: thread-2-8-branch | |
2018-06-18
| ||
08:26 | Update to latest TEA check-in: c9ade9f27a user: jan.nijtmans tags: thread-2-8-branch | |
Changes
Changes to generic/threadCmd.c.
︙ | ︙ | |||
930 931 932 933 934 935 936 | static int ThreadSendObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *const objv[]; /* Argument objects. */ { | | | 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 | static int ThreadSendObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *const objv[]; /* Argument objects. */ { size_t size; int ret, ii = 0, flags = 0; Tcl_ThreadId thrId; const char *script, *arg; Tcl_Obj *var = NULL; ThreadClbkData *clbkPtr = NULL; ThreadSendData *sendPtr = NULL; |
︙ | ︙ | |||
972 973 974 975 976 977 978 | return TCL_ERROR; } if (++ii >= objc) { goto usage; } script = Tcl_GetString(objv[ii]); | | < > > > | | | 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 | return TCL_ERROR; } if (++ii >= objc) { goto usage; } script = Tcl_GetString(objv[ii]); size = objv[ii]->length+1; if (++ii < objc) { var = objv[ii]; } if (var && (flags & THREAD_SEND_WAIT) == 0) { const char *varName = Tcl_GetString(var); size_t vsize = objv[ii]->length + 1; if (thrId == Tcl_GetCurrentThread()) { /* * FIXME: Do something for callbacks to self */ Tcl_SetObjResult(interp, Tcl_NewStringObj("can't notify self", -1)); return TCL_ERROR; } /* * Prepare record for the callback. This is asynchronously * posted back to us when the target thread finishes processing. * We should do a vwait on the "var" to get notified. */ clbkPtr = (ThreadClbkData*)ckalloc(sizeof(ThreadClbkData)); clbkPtr->execProc = ThreadClbkSetVar; clbkPtr->freeProc = threadSendFree; clbkPtr->interp = interp; clbkPtr->threadId = Tcl_GetCurrentThread(); clbkPtr->clientData = (ClientData)memcpy(ckalloc(vsize), varName, vsize); } /* * Prepare job record for the target thread */ sendPtr = (ThreadSendData*)ckalloc(sizeof(ThreadSendData)); sendPtr->interp = NULL; /* Signal to use thread main interp */ sendPtr->execProc = ThreadSendEval; sendPtr->freeProc = threadSendFree; sendPtr->clientData = (ClientData)memcpy(ckalloc(size), script, size); ret = ThreadSend(interp, thrId, sendPtr, clbkPtr, flags); if (var && (flags & THREAD_SEND_WAIT)) { /* * Leave job's result in passed variable |
︙ | ︙ | |||
1059 1060 1061 1062 1063 1064 1065 | ThreadBroadcastObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *const objv[]; /* Argument objects. */ { int ii, nthreads; | | | | 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 | ThreadBroadcastObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *const objv[]; /* Argument objects. */ { int ii, nthreads; size_t size; const char *script; Tcl_ThreadId *thrIdArray; ThreadSendData *sendPtr, job; Init(interp); if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "script"); return TCL_ERROR; } script = Tcl_GetString(objv[1]); size = objv[1]->length + 1; /* * Get the list of known threads. Note that this one may * actually change (thread may exit or otherwise cease to * exist) while we circle in the loop below. We really do * not care about that here since we don't return any * script results to the caller. |
︙ | ︙ | |||
1111 1112 1113 1114 1115 1116 1117 | for (ii = 0; ii < nthreads; ii++) { if (thrIdArray[ii] == Tcl_GetCurrentThread()) { continue; /* Do not broadcast self */ } sendPtr = (ThreadSendData*)ckalloc(sizeof(ThreadSendData)); *sendPtr = job; | | | 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 | for (ii = 0; ii < nthreads; ii++) { if (thrIdArray[ii] == Tcl_GetCurrentThread()) { continue; /* Do not broadcast self */ } sendPtr = (ThreadSendData*)ckalloc(sizeof(ThreadSendData)); *sendPtr = job; sendPtr->clientData = (ClientData)memcpy(ckalloc(size), script, size); ThreadSend(interp, thrIdArray[ii], sendPtr, NULL, THREAD_SEND_HEAD); } ckfree((char*)thrIdArray); Tcl_ResetResult(interp); return TCL_OK; |
︙ | ︙ | |||
3251 3252 3253 3254 3255 3256 3257 | static void ThreadSetResult(interp, code, resultPtr) Tcl_Interp *interp; int code; ThreadEventResult *resultPtr; { | | | | | | | | | | | | | 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 | static void ThreadSetResult(interp, code, resultPtr) Tcl_Interp *interp; int code; ThreadEventResult *resultPtr; { size_t size; const char *errorCode, *errorInfo, *result; if (interp == NULL) { code = TCL_ERROR; errorInfo = ""; errorCode = "THREAD"; result = "no target interp!"; size = strlen(result); resultPtr->result = (size) ? memcpy(ckalloc(1+size), result, 1+size) : threadEmptyResult; } else { result = Tcl_GetString(Tcl_GetObjResult(interp)); size = Tcl_GetObjResult(interp)->length; resultPtr->result = (size) ? memcpy(ckalloc(1+size), result, 1+size) : threadEmptyResult; if (code == TCL_ERROR) { errorCode = Tcl_GetVar2(interp, "errorCode", NULL, TCL_GLOBAL_ONLY); errorInfo = Tcl_GetVar2(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY); } else { errorCode = NULL; errorInfo = NULL; } } resultPtr->code = code; if (errorCode != NULL) { size = strlen(errorCode) + 1; resultPtr->errorCode = memcpy(ckalloc(size), errorCode, size); } else { resultPtr->errorCode = NULL; } if (errorInfo != NULL) { size = strlen(errorInfo) + 1; resultPtr->errorInfo = memcpy(ckalloc(size), errorInfo, size); } else { resultPtr->errorInfo = NULL; } } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
3538 3539 3540 3541 3542 3543 3544 | code = TCL_OK; /* Return success. */ } } if (resultPtr) { Tcl_MutexLock(&threadMutex); resultPtr->resultCode = code; if (msg != NULL) { | | | | 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 | code = TCL_OK; /* Return success. */ } } if (resultPtr) { Tcl_MutexLock(&threadMutex); resultPtr->resultCode = code; if (msg != NULL) { size_t size = strlen(msg)+1; resultPtr->resultMsg = memcpy(ckalloc(size), msg, size); } Tcl_ConditionNotify(&resultPtr->done); Tcl_MutexUnlock(&threadMutex); } return 1; } |
︙ | ︙ |