1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-22 17:39:53 +03:00

Fix a deadlock when Run() to create a process. Child forked will inherit

state of global mutex which may be in intermidiate taken status by one of
threads of the parent, then in child process it tries to get this mutex
and is always pending. One example of mutex is malloc_lock, and there are more.
This commit is contained in:
ajeecai 2016-10-09 14:23:25 +08:00
parent 1e17c9bcfd
commit 69d132e997

47
src/Mayaqua/Unix.c Normal file → Executable file
View File

@ -1162,7 +1162,9 @@ bool UnixRunW(wchar_t *filename, wchar_t *arg, bool hide, bool wait)
bool UnixRun(char *filename, char *arg, bool hide, bool wait) bool UnixRun(char *filename, char *arg, bool hide, bool wait)
{ {
TOKEN_LIST *t; TOKEN_LIST *t;
char **args;
UINT ret; UINT ret;
// Validate arguments // Validate arguments
if (filename == NULL) if (filename == NULL)
{ {
@ -1173,6 +1175,25 @@ bool UnixRun(char *filename, char *arg, bool hide, bool wait)
arg = ""; arg = "";
} }
Print("", filename, arg);
t = ParseToken(arg, " ");
if (t == NULL)
{
return false;
}
else
{
UINT num_args;
UINT i;
num_args = t->NumTokens + 2;
args = ZeroMalloc(sizeof(char *) * num_args);
args[0] = filename;
for (i = 1;i < num_args - 1;i++)
{
args[i] = t->Token[i - 1];
}
}
// Create a child process // Create a child process
ret = fork(); ret = fork();
if (ret == -1) if (ret == -1)
@ -1183,39 +1204,21 @@ bool UnixRun(char *filename, char *arg, bool hide, bool wait)
if (ret == 0) if (ret == 0)
{ {
Print("", filename, arg);
// Child process // Child process
if (hide) if (hide)
{ {
// Close the standard I/O // Close the standard I/O
UnixCloseIO(); UnixCloseIO();
} }
execvp(filename, args);
t = ParseToken(arg, " "); AbortExit();
if (t == NULL)
{
AbortExit();
}
else
{
char **args;
UINT num_args;
UINT i;
num_args = t->NumTokens + 2;
args = ZeroMalloc(sizeof(char *) * num_args);
args[0] = filename;
for (i = 1;i < num_args - 1;i++)
{
args[i] = t->Token[i - 1];
}
execvp(filename, args);
AbortExit();
}
} }
else else
{ {
// Parent process // Parent process
pid_t pid = (pid_t)ret; pid_t pid = (pid_t)ret;
Free(args);
FreeToken(t);
if (wait) if (wait)
{ {