Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
b08ea0fc
Commit
b08ea0fc
authored
4 years ago
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
windows下子进程支持日志重定向、等待子进程推出、获取子进程退出码等特性
parent
8ef8c91f
显示空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
105 行增加
和
23 行删除
+105
-23
server/FFmpegSource.cpp
+4
-7
server/Process.cpp
+101
-16
没有找到文件。
server/FFmpegSource.cpp
查看文件 @
b08ea0fc
...
...
@@ -24,19 +24,16 @@ const string kSnap = FFmpeg_FIELD"snap";
onceToken
token
([]()
{
#ifdef _WIN32
string
ffmpeg_bin
=
System
::
execute
(
"where ffmpeg"
);
//windows下先关闭FFmpeg日志(目前不支持日志重定向)
mINI
::
Instance
()[
kCmd
]
=
"%s -re -i %s -loglevel quiet -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s"
;
mINI
::
Instance
()[
kSnap
]
=
"%s -i %s -loglevel quiet -y -f mjpeg -t 0.001 %s"
;
string
ffmpeg_bin
=
trim
(
System
::
execute
(
"where ffmpeg"
));
#else
string
ffmpeg_bin
=
System
::
execute
(
"which ffmpeg"
);
mINI
::
Instance
()[
kCmd
]
=
"%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s"
;
mINI
::
Instance
()[
kSnap
]
=
"%s -i %s -y -f mjpeg -t 0.001 %s"
;
string
ffmpeg_bin
=
trim
(
System
::
execute
(
"which ffmpeg"
));
#endif
//默认ffmpeg命令路径为环境变量中路径
mINI
::
Instance
()[
kBin
]
=
ffmpeg_bin
.
empty
()
?
"ffmpeg"
:
ffmpeg_bin
;
//ffmpeg日志保存路径
mINI
::
Instance
()[
kLog
]
=
"./ffmpeg/ffmpeg.log"
;
mINI
::
Instance
()[
kCmd
]
=
"%s -re -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s"
;
mINI
::
Instance
()[
kSnap
]
=
"%s -i %s -y -f mjpeg -t 0.001 %s"
;
});
}
...
...
This diff is collapsed.
Click to expand it.
server/Process.cpp
查看文件 @
b08ea0fc
...
...
@@ -16,6 +16,7 @@
#else
//#include <TlHelp32.h>
#include <windows.h>
#include <io.h>
#endif
#include <stdexcept>
...
...
@@ -31,23 +32,44 @@ using namespace toolkit;
void
Process
::
run
(
const
string
&
cmd
,
const
string
&
log_file_tmp
)
{
kill
(
2000
);
#ifdef _WIN32
STARTUPINFO
si
;
PROCESS_INFORMATION
pi
;
ZeroMemory
(
&
si
,
sizeof
(
si
));
//结构体初始化;
ZeroMemory
(
&
pi
,
sizeof
(
pi
));
STARTUPINFO
si
=
{
0
};
PROCESS_INFORMATION
pi
=
{
0
};
string
log_file
;
if
(
log_file_tmp
.
empty
())
{
//未指定子进程日志文件时,重定向至/dev/null
log_file
=
"NUL"
;
}
else
{
log_file
=
StrPrinter
<<
log_file_tmp
<<
"."
<<
getCurrentMillisecond
();
}
LPTSTR
lpDir
=
const_cast
<
char
*>
(
cmd
.
data
());
//重定向shell日志至文件
auto
fp
=
File
::
create_file
(
log_file
.
data
(),
"ab"
);
if
(
!
fp
)
{
fprintf
(
stderr
,
"open log file %s failed:%d(%s)
\r\n
"
,
log_file
.
data
(),
errno
,
strerror
(
errno
));
}
else
{
auto
log_fd
=
(
HANDLE
)(
_get_osfhandle
(
fileno
(
fp
)));
// dup to stdout and stderr.
si
.
wShowWindow
=
SW_HIDE
;
// STARTF_USESHOWWINDOW:The wShowWindow member contains additional information.
// STARTF_USESTDHANDLES:The hStdInput, hStdOutput, and hStdError members contain additional information.
si
.
dwFlags
=
STARTF_USESHOWWINDOW
|
STARTF_USESTDHANDLES
;
si
.
hStdError
=
log_fd
;
si
.
hStdOutput
=
log_fd
;
}
if
(
CreateProcess
(
NULL
,
lpDir
,
NULL
,
NULL
,
FALSE
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
)){
LPTSTR
lpDir
=
const_cast
<
char
*>
(
cmd
.
data
());
if
(
CreateProcess
(
NULL
,
lpDir
,
NULL
,
NULL
,
TRUE
,
0
,
NULL
,
NULL
,
&
si
,
&
pi
)){
//下面两行关闭句柄,解除本进程和新进程的关系,不然有可能 不小心调用TerminateProcess函数关掉子进程
CloseHandle
(
pi
.
hProcess
);
CloseHandle
(
pi
.
hThread
);
_pid
=
pi
.
dwProcessId
;
fprintf
(
fp
,
"
\r\n\r\n
#### pid=%d,cmd=%s #####
\r\n\r\n
"
,
_pid
,
cmd
.
data
());
InfoL
<<
"start child proces "
<<
_pid
;
}
else
{
WarnL
<<
"start child proces fail: "
<<
GetLastError
();
WarnL
<<
"start child proces fail: "
<<
get_uv_errmsg
();
}
fclose
(
fp
);
#else
_pid
=
fork
();
if
(
_pid
<
0
)
{
...
...
@@ -125,16 +147,42 @@ static bool s_wait(pid_t pid,int *exit_code_ptr,bool block) {
if
(
pid
<=
0
)
{
return
false
;
}
int
status
=
0
;
#ifdef _WIN32
HANDLE
hProcess
=
NULL
;
hProcess
=
OpenProcess
(
PROCESS_TERMINATE
,
FALSE
,
pid
);
//打开目标进程
if
(
hProcess
==
NULL
)
{
hProcess
=
OpenProcess
(
PROCESS_ALL_ACCESS
,
FALSE
,
pid
);
//打开目标进程
if
(
!
hProcess
)
{
WarnL
<<
"OpenProcess failed:"
<<
get_uv_errmsg
();
return
false
;
}
DWORD
code
=
0
;
if
(
block
)
{
//一直等待
code
=
WaitForSingleObject
(
hProcess
,
INFINITE
);
}
else
{
code
=
WaitForSingleObject
(
hProcess
,
0
);
}
if
(
code
==
WAIT_FAILED
||
code
==
WAIT_OBJECT_0
){
//子进程已经退出了,获取子进程退出代码
DWORD
exitCode
=
0
;
if
(
GetExitCodeProcess
(
hProcess
,
&
exitCode
)
&&
exit_code_ptr
){
*
exit_code_ptr
=
exitCode
;
}
CloseHandle
(
hProcess
);
return
false
;
}
CloseHandle
(
hProcess
);
if
(
code
==
WAIT_TIMEOUT
){
//子进程还在线
return
true
;
}
//不太可能运行到此处
WarnL
<<
"WaitForSingleObject ret:"
<<
code
;
return
false
;
#else
int
status
=
0
;
pid_t
p
=
waitpid
(
pid
,
&
status
,
block
?
0
:
WNOHANG
);
int
exit_code
=
(
status
&
0xFF00
)
>>
8
;
if
(
exit_code_ptr
)
{
...
...
@@ -148,10 +196,41 @@ static bool s_wait(pid_t pid,int *exit_code_ptr,bool block) {
InfoL
<<
"process terminated, pid="
<<
pid
<<
", exit code="
<<
exit_code
;
return
false
;
}
return
true
;
#endif // _WIN32
}
return
true
;
#ifdef _WIN32
// Inspired from http://stackoverflow.com/a/15281070/1529139
// and http://stackoverflow.com/q/40059902/1529139
bool
signalCtrl
(
DWORD
dwProcessId
,
DWORD
dwCtrlEvent
){
bool
success
=
false
;
DWORD
thisConsoleId
=
GetCurrentProcessId
();
// Leave current console if it exists
// (otherwise AttachConsole will return ERROR_ACCESS_DENIED)
bool
consoleDetached
=
(
FreeConsole
()
!=
FALSE
);
if
(
AttachConsole
(
dwProcessId
)
!=
FALSE
){
// Add a fake Ctrl-C handler for avoid instant kill is this console
// WARNING: do not revert it or current program will be also killed
SetConsoleCtrlHandler
(
nullptr
,
true
);
success
=
(
GenerateConsoleCtrlEvent
(
dwCtrlEvent
,
0
)
!=
FALSE
);
FreeConsole
();
}
if
(
consoleDetached
){
// Create a new console if previous was deleted by OS
if
(
AttachConsole
(
thisConsoleId
)
==
FALSE
){
int
errorCode
=
GetLastError
();
if
(
errorCode
==
31
){
// 31=ERROR_GEN_FAILURE
AllocConsole
();
}
}
}
return
success
;
}
#endif // _WIN32
static
void
s_kill
(
pid_t
pid
,
int
max_delay
,
bool
force
){
if
(
pid
<=
0
)
{
...
...
@@ -161,13 +240,20 @@ static void s_kill(pid_t pid,int max_delay,bool force){
#ifdef _WIN32
HANDLE
hProcess
=
NULL
;
hProcess
=
OpenProcess
(
PROCESS_TERMINATE
,
FALSE
,
pid
);
//打开目标进程
if
(
hProcess
==
NULL
)
{
WarnL
<<
"
\n
Open Process fAiled: "
<<
GetLastError
();
if
(
!
hProcess
)
{
//子进程可能已经推出了
return
;
}
if
(
force
){
//强制关闭
DWORD
ret
=
TerminateProcess
(
hProcess
,
0
);
//结束目标进程
CloseHandle
(
hProcess
);
if
(
ret
==
0
)
{
WarnL
<<
GetLastError
;
WarnL
<<
"TerminateProcess "
<<
pid
<<
" failed:"
<<
get_uv_errmsg
();
}
}
else
{
//非强制关闭,发生Ctr+C信号
signalCtrl
(
pid
,
CTRL_C_EVENT
);
}
#else
if
(
::
kill
(
pid
,
force
?
SIGKILL
:
SIGTERM
)
==
-
1
)
{
...
...
@@ -177,7 +263,6 @@ static void s_kill(pid_t pid,int max_delay,bool force){
}
#endif // _WIN32
if
(
force
){
//发送SIGKILL信号后,阻塞等待退出
s_wait
(
pid
,
NULL
,
true
);
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论