summaryrefslogtreecommitdiffstats
path: root/win/tclWinPipe.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tclWinPipe.c')
-rw-r--r--win/tclWinPipe.c506
1 files changed, 322 insertions, 184 deletions
diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c
index 597d5df..a001816 100644
--- a/win/tclWinPipe.c
+++ b/win/tclWinPipe.c
@@ -124,8 +124,7 @@ typedef struct PipeInfo {
* write. Set to 0 if no error has been
* detected. This word is shared with the
* writer thread so access must be
- * synchronized with the writable object.
- */
+ * synchronized with the writable object. */
char *writeBuf; /* Current background output buffer. Access is
* synchronized with the writable object. */
int writeBufLen; /* Size of write buffer. Access is
@@ -191,7 +190,7 @@ static DWORD WINAPI PipeReaderThread(LPVOID arg);
static void PipeSetupProc(ClientData clientData, int flags);
static void PipeWatchProc(ClientData instanceData, int mask);
static DWORD WINAPI PipeWriterThread(LPVOID arg);
-static int TempFileName(TCHAR name[MAX_PATH]);
+static int TempFileName(WCHAR name[MAX_PATH]);
static int WaitForRead(PipeInfo *infoPtr, int blocking);
static void PipeThreadActionProc(ClientData instanceData,
int action);
@@ -218,7 +217,7 @@ static const Tcl_ChannelType pipeChannelType = {
NULL, /* handler proc. */
NULL, /* wide seek proc */
PipeThreadActionProc, /* thread action proc */
- NULL /* truncate */
+ NULL /* truncate */
};
/*
@@ -463,10 +462,10 @@ TclWinMakeFile(
static int
TempFileName(
- TCHAR name[MAX_PATH]) /* Buffer in which name for temporary file
+ WCHAR name[MAX_PATH]) /* Buffer in which name for temporary file
* gets stored. */
{
- const TCHAR *prefix = TEXT("TCL");
+ const WCHAR *prefix = L"TCL";
if (GetTempPath(MAX_PATH, name) != 0) {
if (GetTempFileName(name, prefix, 0, name) != 0) {
return 1;
@@ -533,7 +532,7 @@ TclpOpenFile(
HANDLE handle;
DWORD accessMode, createMode, shareMode, flags;
Tcl_DString ds;
- const TCHAR *nativePath;
+ const WCHAR *nativePath;
/*
* Map the access bits to the NT access mode.
@@ -650,7 +649,7 @@ TclFile
TclpCreateTempFile(
const char *contents) /* String to write into temp file, or NULL. */
{
- TCHAR name[MAX_PATH];
+ WCHAR name[MAX_PATH];
const char *native;
Tcl_DString dstring;
HANDLE handle;
@@ -744,7 +743,7 @@ TclpCreateTempFile(
Tcl_Obj *
TclpTempFileName(void)
{
- TCHAR fileName[MAX_PATH];
+ WCHAR fileName[MAX_PATH];
if (TempFileName(fileName) == 0) {
return NULL;
@@ -936,7 +935,7 @@ TclpCreateProcess(
* process. */
{
int result, applType, createFlags;
- Tcl_DString cmdLine; /* Complete command line (TCHAR). */
+ Tcl_DString cmdLine; /* Complete command line (WCHAR). */
STARTUPINFO startInfo;
PROCESS_INFORMATION procInfo;
SECURITY_ATTRIBUTES secAtts;
@@ -1048,7 +1047,7 @@ TclpCreateProcess(
* sink.
*/
- startInfo.hStdOutput = CreateFile(TEXT("NUL:"), GENERIC_WRITE, 0,
+ startInfo.hStdOutput = CreateFile(L"NUL:", GENERIC_WRITE, 0,
&secAtts, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
} else {
DuplicateHandle(hProcess, outputHandle, hProcess,
@@ -1068,7 +1067,7 @@ TclpCreateProcess(
* sink.
*/
- startInfo.hStdError = CreateFile(TEXT("NUL:"), GENERIC_WRITE, 0,
+ startInfo.hStdError = CreateFile(L"NUL:", GENERIC_WRITE, 0,
&secAtts, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
} else {
DuplicateHandle(hProcess, errorHandle, hProcess, &startInfo.hStdError,
@@ -1134,7 +1133,7 @@ TclpCreateProcess(
BuildCommandLine(execPath, argc, argv, &cmdLine);
- if (CreateProcess(NULL, (TCHAR *) Tcl_DStringValue(&cmdLine),
+ if (CreateProcess(NULL, (WCHAR *) Tcl_DStringValue(&cmdLine),
NULL, NULL, TRUE, (DWORD) createFlags, NULL, NULL, &startInfo,
&procInfo) == 0) {
TclWinConvertError(GetLastError());
@@ -1260,14 +1259,14 @@ ApplicationType(
{
int applType, i, nameLen, found;
HANDLE hFile;
- TCHAR *rest;
+ WCHAR *rest;
char *ext;
char buf[2];
DWORD attr, read;
IMAGE_DOS_HEADER header;
Tcl_DString nameBuf, ds;
- const TCHAR *nativeName;
- TCHAR nativeFullPath[MAX_PATH];
+ const WCHAR *nativeName;
+ WCHAR nativeFullPath[MAX_PATH];
static const char extensions[][5] = {"", ".com", ".exe", ".bat", ".cmd"};
/*
@@ -1428,9 +1427,12 @@ ApplicationType(
static const char *
BuildCmdLineBypassBS(
const char *current,
- const char **bspos
-) {
- /* mark first backslash possition */
+ const char **bspos)
+{
+ /*
+ * Mark first backslash position.
+ */
+
if (!*bspos) {
*bspos = current;
}
@@ -1445,14 +1447,14 @@ QuoteCmdLineBackslash(
Tcl_DString *dsPtr,
const char *start,
const char *current,
- const char *bspos
-) {
+ const char *bspos)
+{
if (!bspos) {
- if (current > start) { /* part before current (special) */
+ if (current > start) { /* part before current (special) */
Tcl_DStringAppend(dsPtr, start, (int) (current - start));
}
} else {
- if (bspos > start) { /* part before first backslash */
+ if (bspos > start) { /* part before first backslash */
Tcl_DStringAppend(dsPtr, start, (int) (bspos - start));
}
while (bspos++ < current) { /* each backslash twice */
@@ -1467,38 +1469,59 @@ QuoteCmdLinePart(
const char *start,
const char *special,
const char *specMetaChars,
- const char **bspos
-) {
+ const char **bspos)
+{
if (!*bspos) {
- /* rest before special (before quote) */
+ /*
+ * Rest before special (before quote).
+ */
+
QuoteCmdLineBackslash(dsPtr, start, special, NULL);
start = special;
} else {
- /* rest before first backslash and backslashes into new quoted block */
+ /*
+ * Rest before first backslash and backslashes into new quoted block.
+ */
+
QuoteCmdLineBackslash(dsPtr, start, *bspos, NULL);
start = *bspos;
}
+
/*
- * escape all special chars enclosed in quotes like `"..."`, note that here we
- * don't must escape `\` (with `\`), because it's outside of the main quotes,
- * so `\` remains `\`, but important - not at end of part, because results as
- * before the quote, so `%\%\` should be escaped as `"%\%"\\`).
+ * escape all special chars enclosed in quotes like `"..."`, note that
+ * here we don't must escape `\` (with `\`), because it's outside of the
+ * main quotes, so `\` remains `\`, but important - not at end of part,
+ * because results as before the quote, so `%\%\` should be escaped as
+ * `"%\%"\\`).
*/
+
TclDStringAppendLiteral(dsPtr, "\""); /* opening escape quote-char */
do {
*bspos = NULL;
special++;
if (*special == '\\') {
- /* bypass backslashes (and mark first backslash possition)*/
+ /*
+ * Bypass backslashes (and mark first backslash position).
+ */
+
special = BuildCmdLineBypassBS(special, bspos);
- if (*special == '\0') break;
+ if (*special == '\0') {
+ break;
+ }
}
} while (*special && strchr(specMetaChars, *special));
if (!*bspos) {
- /* unescaped rest before quote */
+ /*
+ * Unescaped rest before quote.
+ */
+
QuoteCmdLineBackslash(dsPtr, start, special, NULL);
} else {
- /* unescaped rest before first backslash (rather belongs to the main block) */
+ /*
+ * Unescaped rest before first backslash (rather belongs to the main
+ * block).
+ */
+
QuoteCmdLineBackslash(dsPtr, start, *bspos, NULL);
}
TclDStringAppendLiteral(dsPtr, "\""); /* closing escape quote-char */
@@ -1512,18 +1535,19 @@ BuildCommandLine(
int argc, /* Number of arguments. */
const char **argv, /* Argument strings in UTF. */
Tcl_DString *linePtr) /* Initialized Tcl_DString that receives the
- * command line (TCHAR). */
+ * command line (WCHAR). */
{
const char *arg, *start, *special, *bspos;
int quote = 0, i;
Tcl_DString ds;
-
- /* characters to enclose in quotes if unpaired quote flag set */
static const char specMetaChars[] = "&|^<>!()%";
- /* character to enclose in quotes in any case (regardless unpaired-flag) */
+ /* Characters to enclose in quotes if unpaired
+ * quote flag set. */
static const char specMetaChars2[] = "%";
-
- /* Quote flags:
+ /* Character to enclose in quotes in any case
+ * (regardless of unpaired-flag). */
+ /*
+ * Quote flags:
* CL_ESCAPE - escape argument;
* CL_QUOTE - enclose in quotes;
* CL_UNPAIRED - previous arguments chain contains unpaired quote-char;
@@ -1554,34 +1578,32 @@ BuildCommandLine(
if (arg[0] == '\0') {
quote = CL_QUOTE;
} else {
- int count;
- Tcl_UniChar ch;
for (start = arg;
- *start != '\0' &&
- (quote & (CL_ESCAPE|CL_QUOTE)) != (CL_ESCAPE|CL_QUOTE);
- start += count
- ) {
- count = Tcl_UtfToUniChar(start, &ch);
- if (count > 1) continue;
- if (Tcl_UniCharIsSpace(ch)) {
- quote |= CL_QUOTE; /* quote only */
- if (bspos) { /* if backslash found - escape & quote */
+ *start != '\0' &&
+ (quote & (CL_ESCAPE|CL_QUOTE)) != (CL_ESCAPE|CL_QUOTE);
+ start++) {
+ if (*start & 0x80) {
+ continue;
+ }
+ if (TclIsSpaceProc(*start)) {
+ quote |= CL_QUOTE; /* quote only */
+ if (bspos) { /* if backslash found, escape & quote */
quote |= CL_ESCAPE;
break;
}
continue;
}
if (strchr(specMetaChars, *start)) {
- quote |= (CL_ESCAPE|CL_QUOTE); /*escape & quote */
+ quote |= (CL_ESCAPE|CL_QUOTE); /* escape & quote */
break;
}
if (*start == '"') {
- quote |= CL_ESCAPE; /* escape only */
+ quote |= CL_ESCAPE; /* escape only */
continue;
}
if (*start == '\\') {
bspos = start;
- if (quote & CL_QUOTE) { /* if quote - escape & quote */
+ if (quote & CL_QUOTE) { /* if quote, escape & quote */
quote |= CL_ESCAPE;
break;
}
@@ -1591,56 +1613,116 @@ BuildCommandLine(
bspos = NULL;
}
if (quote & CL_QUOTE) {
- /* start of argument (main opening quote-char) */
+ /*
+ * Start of argument (main opening quote-char).
+ */
+
TclDStringAppendLiteral(&ds, "\"");
}
if (!(quote & CL_ESCAPE)) {
- /* nothing to escape */
+ /*
+ * Nothing to escape.
+ */
+
Tcl_DStringAppend(&ds, arg, -1);
} else {
start = arg;
for (special = arg; *special != '\0'; ) {
- /* position of `\` is important before quote or at end (equal `\"` because quoted) */
+ /*
+ * Position of `\` is important before quote or at end (equal
+ * `\"` because quoted).
+ */
+
if (*special == '\\') {
- /* bypass backslashes (and mark first backslash possition)*/
+ /*
+ * Bypass backslashes (and mark first backslash position)
+ */
+
special = BuildCmdLineBypassBS(special, &bspos);
- if (*special == '\0') break;
+ if (*special == '\0') {
+ break;
+ }
}
/* ["] */
if (*special == '"') {
- quote ^= CL_UNPAIRED; /* invert unpaired flag - observe unpaired quotes */
- /* add part before (and escape backslashes before quote) */
+ /*
+ * Invert the unpaired flag - observe unpaired quotes
+ */
+
+ quote ^= CL_UNPAIRED;
+
+ /*
+ * Add part before (and escape backslashes before quote).
+ */
+
QuoteCmdLineBackslash(&ds, start, special, bspos);
bspos = NULL;
- /* escape using backslash */
+
+ /*
+ * Escape using backslash
+ */
+
TclDStringAppendLiteral(&ds, "\\\"");
start = ++special;
continue;
}
- /* unpaired (escaped) quote causes special handling on meta-chars */
+
+ /*
+ * Unpaired (escaped) quote causes special handling on
+ * meta-chars
+ */
+
if ((quote & CL_UNPAIRED) && strchr(specMetaChars, *special)) {
- special = QuoteCmdLinePart(&ds, start, special, specMetaChars, &bspos);
- /* start to current or first backslash */
+ special = QuoteCmdLinePart(&ds, start, special,
+ specMetaChars, &bspos);
+
+ /*
+ * Start to current or first backslash
+ */
+
start = !bspos ? special : bspos;
continue;
}
- /* special case for % - should be enclosed always (paired also) */
+
+ /*
+ * Special case for % - should be enclosed always (paired
+ * also)
+ */
+
if (strchr(specMetaChars2, *special)) {
- special = QuoteCmdLinePart(&ds, start, special, specMetaChars2, &bspos);
- /* start to current or first backslash */
+ special = QuoteCmdLinePart(&ds, start, special,
+ specMetaChars2, &bspos);
+
+ /*
+ * Start to current or first backslash.
+ */
+
start = !bspos ? special : bspos;
continue;
}
- /* other not special (and not meta) character */
- bspos = NULL; /* reset last backslash possition (not interesting) */
+
+ /*
+ * Other not special (and not meta) character
+ */
+
+ bspos = NULL; /* reset last backslash position (not
+ * interesting) */
special++;
}
- /* rest of argument (and escape backslashes before closing main quote) */
+
+ /*
+ * Rest of argument (and escape backslashes before closing main
+ * quote)
+ */
+
QuoteCmdLineBackslash(&ds, start, special,
- (quote & CL_QUOTE) ? bspos : NULL);
+ (quote & CL_QUOTE) ? bspos : NULL);
}
if (quote & CL_QUOTE) {
- /* end of argument (main closing quote-char) */
+ /*
+ * End of argument (main closing quote-char)
+ */
+
TclDStringAppendLiteral(&ds, "\"");
}
}
@@ -2178,8 +2260,9 @@ PipeOutputProc(
*errorCode = 0;
/* avoid blocking if pipe-thread exited */
- timeout = ((infoPtr->flags & PIPE_ASYNC) || !TclPipeThreadIsAlive(&infoPtr->writeTI)
- || TclInExit() || TclInThreadExit()) ? 0 : INFINITE;
+ timeout = ((infoPtr->flags & PIPE_ASYNC)
+ || !TclPipeThreadIsAlive(&infoPtr->writeTI)
+ || TclInExit() || TclInThreadExit()) ? 0 : INFINITE;
if (WaitForSingleObject(infoPtr->writable, timeout) == WAIT_TIMEOUT) {
/*
* The writer thread is blocked waiting for a write to complete and
@@ -2217,7 +2300,7 @@ PipeOutputProc(
infoPtr->writeBufLen = toWrite;
infoPtr->writeBuf = ckalloc(toWrite);
}
- memcpy(infoPtr->writeBuf, buf, (size_t) toWrite);
+ memcpy(infoPtr->writeBuf, buf, toWrite);
infoPtr->toWrite = toWrite;
ResetEvent(infoPtr->writable);
TclPipeThreadSignal(&infoPtr->writeTI);
@@ -2365,6 +2448,7 @@ PipeWatchProc(
infoPtr->watchMask = mask & infoPtr->validMask;
if (infoPtr->watchMask) {
Tcl_Time blockTime = { 0, 0 };
+
if (!oldMask) {
infoPtr->nextPtr = tsdPtr->firstPipePtr;
tsdPtr->firstPipePtr = infoPtr;
@@ -2834,7 +2918,7 @@ static DWORD WINAPI
PipeReaderThread(
LPVOID arg)
{
- TclPipeThreadInfo *pipeTI = (TclPipeThreadInfo *)arg;
+ TclPipeThreadInfo *pipeTI = (TclPipeThreadInfo *) arg;
PipeInfo *infoPtr = NULL; /* access info only after success init/wait */
HANDLE handle = NULL;
DWORD count, err;
@@ -2845,13 +2929,14 @@ PipeReaderThread(
* Wait for the main thread to signal before attempting to wait on the
* pipe becoming readable.
*/
+
if (!TclPipeThreadWaitForSignal(&pipeTI)) {
/* exit */
break;
}
if (!infoPtr) {
- infoPtr = (PipeInfo *)pipeTI->clientData;
+ infoPtr = (PipeInfo *) pipeTI->clientData;
handle = ((WinFile *) infoPtr->readFile)->handle;
}
@@ -3104,7 +3189,7 @@ TclpOpenTemporaryFile(
Tcl_Obj *extensionObj,
Tcl_Obj *resultingNameObj)
{
- TCHAR name[MAX_PATH];
+ WCHAR name[MAX_PATH];
char *namePtr;
HANDLE handle;
DWORD flags = FILE_ATTRIBUTE_TEMPORARY;
@@ -3120,17 +3205,17 @@ TclpOpenTemporaryFile(
if (length == 0) {
goto gotError;
}
- namePtr += length * sizeof(TCHAR);
+ namePtr += length * sizeof(WCHAR);
if (basenameObj) {
- const char *string = Tcl_GetString(basenameObj);
+ const char *string = TclGetStringFromObj(basenameObj, &length);
- Tcl_WinUtfToTChar(string, basenameObj->length, &buf);
+ Tcl_WinUtfToTChar(string, length, &buf);
memcpy(namePtr, Tcl_DStringValue(&buf), Tcl_DStringLength(&buf));
namePtr += Tcl_DStringLength(&buf);
Tcl_DStringFree(&buf);
} else {
- const TCHAR *baseStr = TEXT("TCL");
- int length = 3 * sizeof(TCHAR);
+ const WCHAR *baseStr = L"TCL";
+ length = 3 * sizeof(WCHAR);
memcpy(namePtr, baseStr, length);
namePtr += length;
@@ -3197,7 +3282,7 @@ TclPipeThreadCreateTI(
pipeTI = malloc(sizeof(TclPipeThreadInfo));
#else
pipeTI = ckalloc(sizeof(TclPipeThreadInfo));
-#endif
+#endif /* !_PTI_USE_CKALLOC */
pipeTI->evControl = CreateEvent(NULL, FALSE, FALSE, NULL);
pipeTI->state = PTI_STATE_IDLE;
pipeTI->clientData = clientData;
@@ -3236,40 +3321,64 @@ TclPipeThreadWaitForSignal(
}
wakeEvent = pipeTI->evWakeUp;
+
/*
* Wait for the main thread to signal before attempting to do the work.
*/
- /* reset work state of thread (idle/waiting) */
- if ((state = InterlockedCompareExchange(&pipeTI->state,
- PTI_STATE_IDLE, PTI_STATE_WORK)) & (PTI_STATE_STOP|PTI_STATE_END)) {
- /* end of work, check the owner of structure */
+ /*
+ * Reset work state of thread (idle/waiting)
+ */
+
+ state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_IDLE,
+ PTI_STATE_WORK);
+ if (state & (PTI_STATE_STOP|PTI_STATE_END)) {
+ /*
+ * End of work, check the owner of structure.
+ */
+
goto end;
}
- /* entering wait */
- waitResult = WaitForSingleObject(pipeTI->evControl, INFINITE);
- if (waitResult != WAIT_OBJECT_0) {
+ /*
+ * Entering wait
+ */
+ waitResult = WaitForSingleObject(pipeTI->evControl, INFINITE);
+ if (waitResult != WAIT_OBJECT_0) {
/*
* The control event was not signaled, so end of work (unexpected
* behaviour, main thread can be dead?).
*/
+
goto end;
}
- /* try to set work state of thread */
- if ((state = InterlockedCompareExchange(&pipeTI->state,
- PTI_STATE_WORK, PTI_STATE_IDLE)) & (PTI_STATE_STOP|PTI_STATE_END)) {
- /* end of work */
+ /*
+ * Try to set work state of thread
+ */
+
+ state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_WORK,
+ PTI_STATE_IDLE);
+ if (state & (PTI_STATE_STOP|PTI_STATE_END)) {
+ /*
+ * End of work
+ */
+
goto end;
}
- /* signaled to work */
+ /*
+ * Signaled to work.
+ */
+
return 1;
-end:
- /* end of work, check the owner of the TI structure */
+ end:
+ /*
+ * End of work, check the owner of the TI structure.
+ */
+
if (state != PTI_STATE_STOP) {
*pipeTIPtr = NULL;
} else {
@@ -3299,7 +3408,8 @@ end:
int
TclPipeThreadStopSignal(
- TclPipeThreadInfo **pipeTIPtr, HANDLE wakeEvent)
+ TclPipeThreadInfo **pipeTIPtr,
+ HANDLE wakeEvent)
{
TclPipeThreadInfo *pipeTI = *pipeTIPtr;
HANDLE evControl;
@@ -3310,28 +3420,27 @@ TclPipeThreadStopSignal(
}
evControl = pipeTI->evControl;
pipeTI->evWakeUp = wakeEvent;
- switch (
- (state = InterlockedCompareExchange(&pipeTI->state,
- PTI_STATE_STOP, PTI_STATE_IDLE))
- ) {
-
- case PTI_STATE_IDLE:
-
- /* Thread was idle/waiting, notify it goes teardown */
- SetEvent(evControl);
-
- *pipeTIPtr = NULL;
-
- case PTI_STATE_DOWN:
+ state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP,
+ PTI_STATE_IDLE);
+ switch (state) {
+ case PTI_STATE_IDLE:
+ /*
+ * Thread was idle/waiting, notify it goes teardown
+ */
+ SetEvent(evControl);
+ *pipeTIPtr = NULL;
+ case PTI_STATE_DOWN:
return 1;
- default:
- /*
- * Thread works currently, we should try to end it, own the TI structure
- * (because of possible sharing the joint structures with thread)
- */
- InterlockedExchange(&pipeTI->state, PTI_STATE_END);
+ default:
+ /*
+ * Thread works currently, we should try to end it, own the TI
+ * structure (because of possible sharing the joint structures with
+ * thread)
+ */
+
+ InterlockedExchange(&pipeTI->state, PTI_STATE_END);
break;
}
@@ -3374,46 +3483,63 @@ TclPipeThreadStop(
pipeTI = *pipeTIPtr;
evControl = pipeTI->evControl;
pipeTI->evWakeUp = NULL;
+
/*
* Try to sane stop the pipe worker, corresponding its current state
*/
- switch (
- (state = InterlockedCompareExchange(&pipeTI->state,
- PTI_STATE_STOP, PTI_STATE_IDLE))
- ) {
- case PTI_STATE_IDLE:
+ state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP,
+ PTI_STATE_IDLE);
+ switch (state) {
+ case PTI_STATE_IDLE:
+ /*
+ * Thread was idle/waiting, notify it goes teardown
+ */
- /* Thread was idle/waiting, notify it goes teardown */
- SetEvent(evControl);
+ SetEvent(evControl);
- /* we don't need to wait for it at all, thread frees himself (owns the TI structure) */
- pipeTI = NULL;
+ /*
+ * We don't need to wait for it at all, thread frees himself (owns the
+ * TI structure)
+ */
+
+ pipeTI = NULL;
break;
- case PTI_STATE_STOP:
- /* already stopped, thread frees himself (owns the TI structure) */
- pipeTI = NULL;
+ case PTI_STATE_STOP:
+ /*
+ * Already stopped, thread frees himself (owns the TI structure)
+ */
+
+ pipeTI = NULL;
break;
- case PTI_STATE_DOWN:
- /* Thread already down (?), do nothing */
+ case PTI_STATE_DOWN:
+ /*
+ * Thread already down (?), do nothing
+ */
- /* we don't need to wait for it, but we should free pipeTI */
- hThread = NULL;
+ /*
+ * We don't need to wait for it, but we should free pipeTI
+ */
+ hThread = NULL;
break;
/* case PTI_STATE_WORK: */
- default:
+ default:
+ /*
+ * Thread works currently, we should try to end it, own the TI
+ * structure (because of possible sharing the joint structures with
+ * thread)
+ */
+
+ state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_END,
+ PTI_STATE_WORK);
+ if (state == PTI_STATE_DOWN) {
/*
- * Thread works currently, we should try to end it, own the TI structure
- * (because of possible sharing the joint structures with thread)
+ * We don't need to wait for it, but we should free pipeTI
*/
- if ((state = InterlockedCompareExchange(&pipeTI->state,
- PTI_STATE_END, PTI_STATE_WORK)) == PTI_STATE_DOWN
- ) {
- /* we don't need to wait for it, but we should free pipeTI */
- hThread = NULL;
- };
+ hThread = NULL;
+ }
break;
}
@@ -3428,8 +3554,8 @@ TclPipeThreadStop(
GetExitCodeThread(hThread, &exitCode);
if (exitCode == STILL_ACTIVE) {
-
int inExit = (TclInExit() || TclInThreadExit());
+
/*
* Set the stop event so that if the pipe thread is blocked
* somewhere, it may hereafter sane exit cleanly.
@@ -3440,59 +3566,69 @@ TclPipeThreadStop(
/*
* Cancel all sync-IO of this thread (may be blocked there).
*/
+
if (tclWinProcs.cancelSynchronousIo) {
tclWinProcs.cancelSynchronousIo(hThread);
}
/*
- * Wait at most 20 milliseconds for the reader thread to
- * close (regarding TIP#398-fast-exit).
+ * Wait at most 20 milliseconds for the reader thread to close
+ * (regarding TIP#398-fast-exit).
*/
- /* if we want TIP#398-fast-exit. */
- if (WaitForSingleObject(hThread, inExit ? 0 : 20) == WAIT_TIMEOUT) {
+ /*
+ * If we want TIP#398-fast-exit.
+ */
+ if (WaitForSingleObject(hThread, inExit ? 0 : 20) == WAIT_TIMEOUT) {
/*
- * The thread must be blocked waiting for the pipe to
- * become readable in ReadFile(). There isn't a clean way
- * to exit the thread from this condition. We should
- * terminate the child process instead to get the reader
- * thread to fall out of ReadFile with a FALSE. (below) is
- * not the correct way to do this, but will stay here
- * until a better solution is found.
+ * The thread must be blocked waiting for the pipe to become
+ * readable in ReadFile(). There isn't a clean way to exit the
+ * thread from this condition. We should terminate the child
+ * process instead to get the reader thread to fall out of
+ * ReadFile with a FALSE. (below) is not the correct way to do
+ * this, but will stay here until a better solution is found.
*
- * Note that we need to guard against terminating the
- * thread while it is in the middle of Tcl_ThreadAlert
- * because it won't be able to release the notifier lock.
+ * Note that we need to guard against terminating the thread
+ * while it is in the middle of Tcl_ThreadAlert because it
+ * won't be able to release the notifier lock.
*
- * Also note that terminating threads during their initialization or teardown phase
- * may result in ntdll.dll's LoaderLock to remain locked indefinitely.
- * This causes ntdll.dll's LdrpInitializeThread() to deadlock trying to acquire LoaderLock.
- * LdrpInitializeThread() is executed within new threads to perform
- * initialization and to execute DllMain() of all loaded dlls.
- * As a result, all new threads are deadlocked in their initialization phase and never execute,
- * even though CreateThread() reports successful thread creation.
- * This results in a very weird process-wide behavior, which is extremely hard to debug.
+ * Also note that terminating threads during their
+ * initialization or teardown phase may result in ntdll.dll's
+ * LoaderLock to remain locked indefinitely. This causes
+ * ntdll.dll's LdrpInitializeThread() to deadlock trying to
+ * acquire LoaderLock. LdrpInitializeThread() is executed
+ * within new threads to perform initialization and to execute
+ * DllMain() of all loaded dlls. As a result, all new threads
+ * are deadlocked in their initialization phase and never
+ * execute, even though CreateThread() reports successful
+ * thread creation. This results in a very weird process-wide
+ * behavior, which is extremely hard to debug.
*
* THREADS SHOULD NEVER BE TERMINATED. Period.
*
- * But for now, check if thread is exiting, and if so, let it die peacefully.
+ * But for now, check if thread is exiting, and if so, let it
+ * die peacefully.
*
- * Also don't terminate if in exit (otherwise deadlocked in ntdll.dll's).
+ * Also don't terminate if in exit (otherwise deadlocked in
+ * ntdll.dll's).
*/
- if ( pipeTI->state != PTI_STATE_DOWN
- && WaitForSingleObject(hThread,
- inExit ? 50 : 5000) != WAIT_OBJECT_0
- ) {
+ if (pipeTI->state != PTI_STATE_DOWN
+ && WaitForSingleObject(hThread,
+ inExit ? 50 : 5000) != WAIT_OBJECT_0) {
/* BUG: this leaks memory */
if (inExit || !TerminateThread(hThread, 0)) {
- /* in exit or terminate fails, just give thread a chance to exit */
+ /*
+ * in exit or terminate fails, just give thread a
+ * chance to exit
+ */
+
if (InterlockedExchange(&pipeTI->state,
PTI_STATE_STOP) != PTI_STATE_DOWN) {
pipeTI = NULL;
}
- };
+ }
}
}
}
@@ -3504,11 +3640,11 @@ TclPipeThreadStop(
SetEvent(pipeTI->evWakeUp);
}
CloseHandle(pipeTI->evControl);
-# ifndef _PTI_USE_CKALLOC
+#ifndef _PTI_USE_CKALLOC
free(pipeTI);
-# else
+#else
ckfree(pipeTI);
-# endif
+#endif /* !_PTI_USE_CKALLOC */
}
}
@@ -3537,28 +3673,30 @@ TclPipeThreadExit(
{
LONG state;
TclPipeThreadInfo *pipeTI = *pipeTIPtr;
+
/*
* If state of thread was set to stop (exactly), we can sane free its info
* structure, otherwise it is shared with main thread, so main thread will
* own it.
*/
+
if (!pipeTI) {
return;
}
*pipeTIPtr = NULL;
- if ((state = InterlockedExchange(&pipeTI->state,
- PTI_STATE_DOWN)) == PTI_STATE_STOP) {
+ state = InterlockedExchange(&pipeTI->state, PTI_STATE_DOWN);
+ if (state == PTI_STATE_STOP) {
CloseHandle(pipeTI->evControl);
if (pipeTI->evWakeUp) {
SetEvent(pipeTI->evWakeUp);
}
-# ifndef _PTI_USE_CKALLOC
+#ifndef _PTI_USE_CKALLOC
free(pipeTI);
-# else
+#else
ckfree(pipeTI);
/* be sure all subsystems used are finalized */
Tcl_FinalizeThread();
-# endif
+#endif /* !_PTI_USE_CKALLOC */
}
}