Skip to content

Commit 975e71d

Browse files
committed
Changed the stream redirection functions to FILE*
Usage of file descriptors caused some stability bugs on some new platforms (mostly ucrt). As the multithreading was included in previous versions and the "standard streams" separated for each thread (fInput, fError, fOutput), there is really no need to perform any dup() or dup2() on files descriptors (except for external programs). This new implementation increases portability as uses mostly only c standard functions, and speed also as it only use variables susbstition instead of system level calls.
1 parent b4766e6 commit 975e71d

18 files changed

Lines changed: 312 additions & 304 deletions

pbat/Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ SRC_FILES := \
5353
./errors/pBat_Errors.c ./lang/pBat_Lang.c ./core/pBat_Debug.c \
5454
./core/pBat_FilePath.c ./core/pBat_ParseBlock.c ./lang/pBat_ShowHelp.c \
5555
./core/pBat_ExpandDef.c ./core/pBat_ReadScript.c ./core/pBat_Clone.c \
56-
./core/pBat_EsCache.c ./command/pBat_Def.c ./command/pBat_Ask.c \
56+
./core/pBat_EsCache.c ./core/pBat_Pipe.c \
57+
./command/pBat_Def.c ./command/pBat_Ask.c \
5758
./command/pBat_Block.c ./command/pBat_Call.c ./command/pBat_Cd.c \
5859
./command/pBat_Cls.c ./command/pBat_Color.c ./command/pBat_Copy.c \
5960
./command/pBat_Del.c ./command/pBat_Dir.c ./command/pBat_Echo.c \
@@ -70,7 +71,7 @@ SRC_FILES := \
7071
./core/pBat_Exec.c ./core/pBat_Prompt.c ./command/pBat_Pecho.c \
7172
./command/pBat_CommandInfo.c ./core/pBat_Completion.c \
7273
./command/pBat_Timeout.c ./command/pBat_Mod.c \
73-
./command/pBat_Ver.c ./command/pBat_Locale.c $(SRC_LINENOISE) \
74+
./command/pBat_Ver.c ./command/pBat_Locale.c $(SRC_LINENOISE)
7475

7576
OBJ_FILES := $(SRC_FILES:.c=.o) $(OBJ_RC)
7677

pbat/command/pBat_For.c

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,8 +1183,8 @@ int pBat_ForVarCheckAssignment(FORINFO* lpfrInfo)
11831183
int pBat_ForMakeInputInfo(ESTR* lpInput, INPUTINFO* lpipInfo, FORINFO* lpfrInfo)
11841184
{
11851185
int bUsebackq=lpfrInfo->bUsebackq,
1186-
iInputType,
1187-
iPipeFd[2];
1186+
iInputType;
1187+
FILE *pipef[2];
11881188
int status;
11891189

11901190
char *lpToken=pBat_EsToChar(lpInput);
@@ -1295,7 +1295,7 @@ int pBat_ForMakeInputInfo(ESTR* lpInput, INPUTINFO* lpipInfo, FORINFO* lpfrInfo)
12951295
/* Serialize this with pBat_RunFile() */
12961296
PBAT_RUNFILE_LOCK();
12971297

1298-
if (_pBat_Pipe(iPipeFd, 4096, O_BINARY) == -1)
1298+
if (pBat_Pipe(pipef) == -1)
12991299
pBat_ShowErrorMessage(PBAT_CREATE_PIPE | PBAT_PRINT_C_ERROR ,
13001300
__FILE__ "/pBat_MakeInputInfo()",
13011301
PBAT_CREATE_PIPE);
@@ -1304,7 +1304,7 @@ int pBat_ForMakeInputInfo(ESTR* lpInput, INPUTINFO* lpipInfo, FORINFO* lpfrInfo)
13041304

13051305
/* Launch the actual command from which we get input on a separate
13061306
pBat thread */
1307-
if ((status = pBat_ForInputProcess(lpInput, lpipInfo, iPipeFd)))
1307+
if ((status = pBat_ForInputProcess(lpInput, lpipInfo, pipef)))
13081308
return status;
13091309

13101310

@@ -1351,8 +1351,7 @@ void pBat_ExecuteForSubCommand(struct pipe_launch_data_t* arg)
13511351
{
13521352
BLOCKINFO bkBlock;
13531353

1354-
lppsStreamStack = pBat_OpenOutputD(lppsStreamStack, arg->fdout, PBAT_STDOUT);
1355-
close(arg->fdout);
1354+
lppsStreamStack = pBat_OpenOutputF(lppsStreamStack, arg->out, PBAT_STDOUT);
13561355

13571356
bIgnoreExit = TRUE;
13581357

@@ -1368,38 +1367,24 @@ void pBat_ExecuteForSubCommand(struct pipe_launch_data_t* arg)
13681367

13691368
}
13701369

1371-
int pBat_ForInputProcess(ESTR* lpInput, INPUTINFO* lpipInfo, int* iPipeFd)
1370+
int pBat_ForInputProcess(ESTR* lpInput, INPUTINFO* lpipInfo, FILE** pipef)
13721371
{
13731372
struct pipe_launch_data_t* param;
1374-
FILE* pFile;
1375-
1376-
if (!(pFile=fdopen(iPipeFd[0], "rb"))) {
1377-
1378-
pBat_ShowErrorMessage(PBAT_UNABLE_DUPLICATE_FD,
1379-
iPipeFd[0],
1380-
FALSE);
1381-
1382-
close(iPipeFd[0]);
1383-
close(iPipeFd[1]);
1384-
1385-
return PBAT_UNABLE_DUPLICATE_FD;
1386-
1387-
}
13881373

13891374
if ((param = malloc(sizeof(struct pipe_launch_data_t))) == NULL)
13901375
pBat_ShowErrorMessage(PBAT_FAILED_ALLOCATION | PBAT_PRINT_C_ERROR,
13911376
__FILE__ "/pBat_ForInputProcess()", -1);
13921377

13931378

1394-
param->fdout = iPipeFd[1];
1379+
param->out = pipef[1];
13951380
param->str = pBat_EsInit();
13961381

13971382
pBat_EsCpyE(param->str, lpInput);
13981383

13991384
lpipInfo->Info.InputFile.handle
14001385
= pBat_CloneInstance((void (*)(void *))pBat_ExecuteForSubCommand, param);
14011386

1402-
lpipInfo->Info.InputFile.pFile=pFile;
1387+
lpipInfo->Info.InputFile.pFile=pipef[0];
14031388

14041389
lpipInfo->Info.InputFile.lpesFiles[1]=NULL;
14051390
lpipInfo->Info.InputFile.index=0;

pbat/command/pBat_For.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ int pBat_ForAdjustInput(char* lpInput);
172172

173173
int pBat_ForInputParseFileList(FILE_LIST_T* lpList, ESTR* lpInput);
174174

175-
int pBat_ForInputProcess(ESTR* lpInput, INPUTINFO* lpipInfo, int* iPipeFd);
175+
int pBat_ForInputProcess(ESTR* lpInput, INPUTINFO* lpipInfo, FILE** pipef);
176176
/* Start a new process for command input */
177177

178178
int pBat_ForGetInputLine(ESTR* lpReturn, INPUTINFO* lpipInfo);

pbat/core/pBat_Clone.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,6 @@ void* pBat_CloneTrampoline(void* data)
8585
fInput = cloned->fInput;
8686
fOutput = cloned->fOutput;
8787
fError = cloned->fError;
88-
_fError = fError;
89-
_fOutput = fOutput;
9088

9189
lpAltPromptString = NULL;
9290

@@ -101,6 +99,10 @@ void* pBat_CloneTrampoline(void* data)
10199

102100
pBat_Exit();
103101

102+
fclose(fInput);
103+
fclose(fOutput);
104+
fclose(fError);
105+
104106
pBat_EndThread((void*)iErrorLevel);
105107

106108
return (void*)iErrorLevel;
@@ -146,9 +148,15 @@ int pBat_DuplicateData(struct clone_data_t* data)
146148
| PBAT_PRINT_C_ERROR, \
147149
__FILE__ "/pBat_DuplicateData()", -1)
148150

149-
DUPLICATE_STREAM(data->fInput, fInput, "r");
150-
DUPLICATE_STREAM(data->fOutput, fOutput, "w");
151-
DUPLICATE_STREAM(data->fError, fError, "w");
151+
DUPLICATE_STREAM(data->fInput, fInput, "rb");
152+
DUPLICATE_STREAM(data->fOutput, fOutput, "wb");
153+
DUPLICATE_STREAM(data->fError, fError, "wb");
154+
155+
if (isatty(fileno(fOutput)))
156+
setvbuf(fOutput, NULL, _IONBF, 0);
157+
158+
if (isatty(fileno(fError)))
159+
setvbuf(fError, NULL, _IONBF, 0);
152160

153161
return 0;
154162
}

pbat/core/pBat_Core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "pBat_Exec.h"
5555
#include "pBat_Prompt.h"
5656
#include "pBat_Completion.h"
57+
#include "pBat_Pipe.h"
5758

5859
#if defined(WIN32) && defined(PBAT_USE_LIBCU8)
5960
#include <libcu8.h>

pbat/core/pBat_Exec.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,12 +441,14 @@ int pBat_StartFile(EXECINFO* info, int* error)
441441
if (pBat_LockMutex(&mThreadLock))
442442
pBat_ShowErrorMessage(PBAT_LOCK_MUTEX_ERROR,
443443
__FILE__ "/pBat_StartFile()",
444-
-1);
444+
-1);
445+
PBAT_RUNFILE_LOCK();
445446
pBat_ApplyEnv(lpeEnv);
446447
pBat_ApplyStreams(lppsStreamStack);
447448
status = !ShellExecuteExW(&shinfo);
448449
pBat_UnApplyStreams(lppsStreamStack);
449450
pBat_UnApplyEnv(lpeEnv);
451+
PBAT_RUNFILE_RELEASE();
450452

451453
if (pBat_ReleaseMutex(&mThreadLock))
452454
pBat_ShowErrorMessage(PBAT_RELEASE_MUTEX_ERROR,
@@ -512,11 +514,13 @@ int pBat_StartFile(EXECINFO* info, int* error)
512514
-1);
513515

514516
/* apply pBat internal environment variables */
517+
PBAT_RUNFILE_LOCK();
515518
pBat_ApplyEnv(lpeEnv);
516519
pBat_ApplyStreams(lppsStreamStack);
517520
status = !ShellExecuteExA(&shinfo);
518521
pBat_UnApplyStreams(lppsStreamStack);
519522
pBat_UnApplyEnv(lpeEnv);
523+
PBAT_RUNFILE_RELEASE();
520524

521525
if (pBat_ReleaseMutex(&mThreadLock))
522526
pBat_ShowErrorMessage(PBAT_RELEASE_MUTEX_ERROR,

pbat/core/pBat_ExitInt.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,4 @@ void pBat_Exit(void)
3636
pBat_DirStackFree();
3737

3838
pBat_EsCacheDrop(&ecEstrCache);
39-
40-
/* pBat_WaitForAllThreads(); */
41-
42-
fclose(fInput);
43-
fclose(fOutput);
44-
fclose(fError);
4539
}

pbat/core/pBat_Globals.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ __thread struct dirstack_t dsDirStack; /* current directory stack */
7878

7979
__thread COLOR colColor=PBAT_COLOR_DEFAULT;
8080
__thread FILE* fInput; /* current thread input stream */
81-
__thread FILE *fOutput, *_fOutput; /* current thread output stream */
82-
__thread FILE *fError, *_fError; /* current thread error stream */
81+
__thread FILE *fOutput; /* current thread output stream */
82+
__thread FILE *fError; /* current thread error stream */
8383
/* Note : the underscore prefixed version are internally used to
8484
handle output substitution (eg. 2>&1) to be used as backup and
8585
so prevent unnecessary duplication of files */

pbat/core/pBat_Globals.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ extern __thread COLOR colColor; /* current command prompt colors */
7474
extern __thread INPUT_FILE ifIn; /* current parsed script */
7575
extern __thread ENVBUF* lpeEnv; /* environment variables local to threads */
7676
extern __thread FILE *fInput; /* current thread input stream */
77-
extern __thread FILE *fOutput, *_fOutput; /* current thread output stream */
78-
extern __thread FILE *fError, *_fError; /* current thread error stream */
77+
extern __thread FILE *fOutput; /* current thread output stream */
78+
extern __thread FILE *fError; /* current thread error stream */
7979
extern __thread ENVSTACK* lpesEnv;
8080
extern __thread char lpCurrentDir[FILENAME_MAX]; /* current path */
8181
extern __thread ESTRCACHE ecEstrCache; /* ESTR cache */

pbat/core/pBat_Parse.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,16 @@ typedef struct PARSED_LINE {
4646
struct PARSED_LINE* lppsNode;
4747
} PARSED_LINE;
4848

49-
#define PARSED_STREAM_STDOUT2STDERR 2
50-
#define PARSED_STREAM_STDERR2STDOUT 1
49+
#define PARSED_STREAM_STDOUT2STDERR PBAT_STREAM_SUBST_FERROR
50+
#define PARSED_STREAM_STDERR2STDOUT PBAT_STREAM_SUBST_FERROR
5151

5252
#define PARSED_STREAM_NODE_NONE 0x00
5353
#define PARSED_STREAM_NODE_YES 0x01
5454
#define PARSED_STREAM_NODE_NOT 0x02
5555
#define PARSED_STREAM_NODE_PIPE 0x03
5656
#define PARSED_STREAM_NODE_RESET -1
5757

58-
#define PARSED_STREAM_MODE_TRUNCATE 0x04
58+
#define PARSED_STREAM_MODE_TRUNCATE PBAT_STREAM_MODE_TRUNCATE
5959

6060
PARSED_LINE* pBat_ParseLine(ESTR* lpLine);
6161

0 commit comments

Comments
 (0)