Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
徽霖
Vscode
提交
8a6b8fd5
V
Vscode
项目概览
徽霖
/
Vscode
通知
9
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
Vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
8a6b8fd5
编写于
10月 07, 2016
作者:
S
Sandeep Somavarapu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Clean up thred service
上级
cf6b4b56
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
146 addition
and
138 deletion
+146
-138
src/vs/workbench/services/thread/electron-browser/threadService.ts
...rkbench/services/thread/electron-browser/threadService.ts
+146
-138
未找到文件。
src/vs/workbench/services/thread/electron-browser/threadService.ts
浏览文件 @
8a6b8fd5
...
...
@@ -132,7 +132,13 @@ class ExtensionHostProcessManager {
PIPE_LOGGING
:
'
true
'
,
VERBOSE_LOGGING
:
true
,
VSCODE_WINDOW_ID
:
String
(
this
.
windowService
.
getWindowId
())
})
}),
// We only detach the extension host on windows. Linux and Mac orphan by default
// and detach under Linux and Mac create another process group.
// We detach because we have noticed that when the renderer exits, its child processes
// (i.e. extension host) is taken down in a brutal fashion by the OS
detached
:
!!
isWindows
,
onExtensionHostMessage
};
// Help in case we fail to start it
...
...
@@ -145,20 +151,16 @@ class ExtensionHostProcessManager {
}
// Initialize extension host process with hand shakes
this
.
initializeExtensionHostProcess
=
new
TPromise
<
ChildProcess
>
((
c
,
e
)
=>
{
this
.
initializeExtensionHostProcess
=
this
.
doInitializeExtensionHostProcess
(
opts
);
}
private
doInitializeExtensionHostProcess
(
opts
:
any
):
TPromise
<
ChildProcess
>
{
return
new
TPromise
<
ChildProcess
>
((
c
,
e
)
=>
{
// Resolve additional execution args (e.g. debug)
return
this
.
resolveDebugPort
(
this
.
environmentService
.
debugExtensionHost
.
port
,
port
=>
{
this
.
resolveDebugPort
(
this
.
environmentService
.
debugExtensionHost
.
port
).
then
(
port
=>
{
if
(
port
)
{
opts
.
execArgv
=
[
'
--nolazy
'
,
(
this
.
isExtensionDevelopmentDebugging
?
'
--debug-brk=
'
:
'
--debug=
'
)
+
port
];
}
// We only detach the extension host on windows. Linux and Mac orphan by default
// and detach under Linux and Mac create another process group.
if
(
isWindows
)
{
// We detach because we have noticed that when the renderer exits, its child processes
// (i.e. extension host) is taken down in a brutal fashion by the OS
opts
.
detached
=
true
;
}
// Run Extension Host as fork of current process
this
.
extensionHostProcessHandle
=
fork
(
URI
.
parse
(
require
.
toUrl
(
'
bootstrap
'
)).
fsPath
,
[
'
--type=extensionHost
'
],
opts
);
...
...
@@ -172,159 +174,165 @@ class ExtensionHostProcessManager {
}
// Messages from Extension host
this
.
extensionHostProcessHandle
.
on
(
'
message
'
,
(
msg
)
=>
{
// 1) Host is ready to receive messages, initialize it
if
(
msg
===
'
ready
'
)
{
if
(
this
.
initializeTimer
)
{
window
.
clearTimeout
(
this
.
initializeTimer
);
}
let
initPayload
=
stringify
({
parentPid
:
process
.
pid
,
environment
:
{
appSettingsHome
:
this
.
environmentService
.
appSettingsHome
,
disableExtensions
:
this
.
environmentService
.
disableExtensions
,
userExtensionsHome
:
this
.
environmentService
.
extensionsPath
,
extensionDevelopmentPath
:
this
.
environmentService
.
extensionDevelopmentPath
,
extensionTestsPath
:
this
.
environmentService
.
extensionTestsPath
},
contextService
:
{
workspace
:
this
.
contextService
.
getWorkspace
()
}
});
this
.
extensionHostProcessHandle
.
send
(
initPayload
);
}
// 2) Host is initialized
else
if
(
msg
===
'
initialized
'
)
{
this
.
unsentMessages
.
forEach
(
m
=>
this
.
postMessage
(
m
));
this
.
unsentMessages
=
[];
this
.
extensionHostProcessReady
=
true
;
this
.
extensionHostProcessHandle
.
on
(
'
message
'
,
msg
=>
{
if
(
this
.
onMessaage
(
msg
,
opts
.
onExtensionHostMessage
))
{
c
(
this
.
extensionHostProcessHandle
);
}
// Support logging from extension host
else
if
(
msg
&&
(
<
ILogEntry
>
msg
).
type
===
'
__$console
'
)
{
let
logEntry
:
ILogEntry
=
msg
;
let
args
=
[];
try
{
let
parsed
=
JSON
.
parse
(
logEntry
.
arguments
);
args
.
push
(...
Object
.
getOwnPropertyNames
(
parsed
).
map
(
o
=>
parsed
[
o
]));
}
catch
(
error
)
{
args
.
push
(
logEntry
.
arguments
);
}
// If the first argument is a string, check for % which indicates that the message
// uses substitution for variables. In this case, we cannot just inject our colored
// [Extension Host] to the front because it breaks substitution.
let
consoleArgs
=
[];
if
(
typeof
args
[
0
]
===
'
string
'
&&
args
[
0
].
indexOf
(
'
%
'
)
>=
0
)
{
consoleArgs
=
[
`%c[Extension Host]%c
${
args
[
0
]}
`
,
'
color: blue
'
,
'
color: black
'
,
...
args
.
slice
(
1
)];
}
else
{
consoleArgs
=
[
'
%c[Extension Host]
'
,
'
color: blue
'
,
...
args
];
}
// Send to local console unless we run tests from cli
if
(
!
this
.
isExtensionDevelopmentTestFromCli
)
{
console
[
logEntry
.
severity
].
apply
(
console
,
consoleArgs
);
}
// Log on main side if running tests from cli
if
(
this
.
isExtensionDevelopmentTestFromCli
)
{
ipc
.
send
(
'
vscode:log
'
,
logEntry
);
}
// Broadcast to other windows if we are in development mode
else
if
(
!
this
.
environmentService
.
isBuilt
||
this
.
isExtensionDevelopmentHost
)
{
this
.
windowService
.
broadcast
({
channel
:
EXTENSION_LOG_BROADCAST_CHANNEL
,
payload
:
logEntry
},
this
.
environmentService
.
extensionDevelopmentPath
/* target */
);
}
}
// Any other message goes to the callback
else
{
onExtensionHostMessage
(
msg
);
}
});
// Lifecycle
let
onExit
=
()
=>
this
.
terminate
();
process
.
once
(
'
exit
'
,
onExit
);
this
.
extensionHostProcessHandle
.
on
(
'
error
'
,
(
err
)
=>
{
let
errorMessage
=
toErrorMessage
(
err
);
if
(
errorMessage
===
this
.
lastExtensionHostError
)
{
return
;
// prevent error spam
}
this
.
lastExtensionHostError
=
errorMessage
;
this
.
messageService
.
show
(
Severity
.
Error
,
nls
.
localize
(
'
extensionHostProcess.error
'
,
"
Error from the extension host: {0}
"
,
errorMessage
));
});
this
.
extensionHostProcessHandle
.
on
(
'
exit
'
,
(
code
:
any
,
signal
:
any
)
=>
{
process
.
removeListener
(
'
exit
'
,
onExit
);
if
(
!
this
.
terminating
)
{
// Unexpected termination
if
(
!
this
.
isExtensionDevelopmentHost
)
{
this
.
messageService
.
show
(
Severity
.
Error
,
{
message
:
nls
.
localize
(
'
extensionHostProcess.crash
'
,
"
Extension host terminated unexpectedly. Please reload the window to recover.
"
),
actions
:
[
this
.
instantiationService
.
createInstance
(
ReloadWindowAction
,
ReloadWindowAction
.
ID
,
ReloadWindowAction
.
LABEL
)]
});
console
.
error
(
'
Extension host terminated unexpectedly. Code:
'
,
code
,
'
Signal:
'
,
signal
);
}
// Expected development extension termination: When the extension host goes down we also shutdown the window
else
if
(
!
this
.
isExtensionDevelopmentTestFromCli
)
{
this
.
windowService
.
getWindow
().
close
();
}
// When CLI testing make sure to exit with proper exit code
else
{
ipc
.
send
(
'
vscode:exit
'
,
code
);
}
}
});
this
.
extensionHostProcessHandle
.
on
(
'
error
'
,
(
err
)
=>
this
.
onError
(
err
));
this
.
extensionHostProcessHandle
.
on
(
'
exit
'
,
(
code
:
any
,
signal
:
any
)
=>
this
.
onExit
(
code
,
signal
,
onExit
));
});
},
()
=>
this
.
terminate
());
}
private
resolveDebugPort
(
extensionHostPort
:
number
,
clb
:
(
port
:
number
)
=>
void
):
void
{
// Check for a free debugging port
if
(
typeof
extensionHostPort
===
'
number
'
)
{
return
findFreePort
(
extensionHostPort
,
10
/* try 10 ports */
,
5000
/* try up to 5 seconds */
,
(
port
)
=>
{
private
resolveDebugPort
(
extensionHostPort
:
number
):
TPromise
<
number
>
{
if
(
typeof
extensionHostPort
!==
'
number
'
)
{
return
TPromise
.
wrap
(
void
0
);
}
return
new
TPromise
<
number
>
((
c
,
e
)
=>
{
findFreePort
(
extensionHostPort
,
10
/* try 10 ports */
,
5000
/* try up to 5 seconds */
,
(
port
)
=>
{
if
(
!
port
)
{
console
.
warn
(
'
%c[Extension Host] %cCould not find a free port for debugging
'
,
'
color: blue
'
,
'
color: black
'
);
return
clb
(
void
0
);
c
(
void
0
);
}
if
(
port
!==
extensionHostPort
)
{
console
.
warn
(
'
%c[Extension Host] %cProvided debugging port
'
+
extensionHostPort
+
'
is not free, using
'
+
port
+
'
instead.
'
,
'
color: blue
'
,
'
color: black
'
);
}
if
(
this
.
isExtensionDevelopmentDebugging
)
{
console
.
warn
(
'
%c[Extension Host] %cSTOPPED on first line for debugging on port
'
+
port
,
'
color: blue
'
,
'
color: black
'
);
}
else
{
console
.
info
(
'
%c[Extension Host] %cdebugger listening on port
'
+
port
,
'
color: blue
'
,
'
color: black
'
);
}
return
clb
(
port
);
return
c
(
port
);
});
});
}
// @return `true` if ready
private
onMessaage
(
msg
:
any
,
onExtensionHostMessage
:
(
msg
:
any
)
=>
void
):
boolean
{
// 1) Host is ready to receive messages, initialize it
if
(
msg
===
'
ready
'
)
{
this
.
initializeExtensionHost
();
return
false
;
}
// 2) Host is initialized
if
(
msg
===
'
initialized
'
)
{
this
.
unsentMessages
.
forEach
(
m
=>
this
.
postMessage
(
m
));
this
.
unsentMessages
=
[];
this
.
extensionHostProcessReady
=
true
;
return
true
;
}
// Support logging from extension host
if
(
msg
&&
(
<
ILogEntry
>
msg
).
type
===
'
__$console
'
)
{
this
.
logExtensionHostMessage
(
<
ILogEntry
>
msg
);
return
false
;
}
// Any other message goes to the callback
onExtensionHostMessage
(
msg
);
return
false
;
}
private
initializeExtensionHost
()
{
if
(
this
.
initializeTimer
)
{
window
.
clearTimeout
(
this
.
initializeTimer
);
}
// Nothing to do here
else
{
return
clb
(
void
0
);
let
initPayload
=
stringify
({
parentPid
:
process
.
pid
,
environment
:
{
appSettingsHome
:
this
.
environmentService
.
appSettingsHome
,
disableExtensions
:
this
.
environmentService
.
disableExtensions
,
userExtensionsHome
:
this
.
environmentService
.
extensionsPath
,
extensionDevelopmentPath
:
this
.
environmentService
.
extensionDevelopmentPath
,
extensionTestsPath
:
this
.
environmentService
.
extensionTestsPath
},
contextService
:
{
workspace
:
this
.
contextService
.
getWorkspace
()
}
});
this
.
extensionHostProcessHandle
.
send
(
initPayload
);
}
private
logExtensionHostMessage
(
logEntry
:
ILogEntry
)
{
let
args
=
[];
try
{
let
parsed
=
JSON
.
parse
(
logEntry
.
arguments
);
args
.
push
(...
Object
.
getOwnPropertyNames
(
parsed
).
map
(
o
=>
parsed
[
o
]));
}
catch
(
error
)
{
args
.
push
(
logEntry
.
arguments
);
}
// If the first argument is a string, check for % which indicates that the message
// uses substitution for variables. In this case, we cannot just inject our colored
// [Extension Host] to the front because it breaks substitution.
let
consoleArgs
=
[];
if
(
typeof
args
[
0
]
===
'
string
'
&&
args
[
0
].
indexOf
(
'
%
'
)
>=
0
)
{
consoleArgs
=
[
`%c[Extension Host]%c
${
args
[
0
]}
`
,
'
color: blue
'
,
'
color: black
'
,
...
args
.
slice
(
1
)];
}
else
{
consoleArgs
=
[
'
%c[Extension Host]
'
,
'
color: blue
'
,
...
args
];
}
// Send to local console unless we run tests from cli
if
(
!
this
.
isExtensionDevelopmentTestFromCli
)
{
console
[
logEntry
.
severity
].
apply
(
console
,
consoleArgs
);
}
// Log on main side if running tests from cli
if
(
this
.
isExtensionDevelopmentTestFromCli
)
{
ipc
.
send
(
'
vscode:log
'
,
logEntry
);
}
// Broadcast to other windows if we are in development mode
else
if
(
!
this
.
environmentService
.
isBuilt
||
this
.
isExtensionDevelopmentHost
)
{
this
.
windowService
.
broadcast
({
channel
:
EXTENSION_LOG_BROADCAST_CHANNEL
,
payload
:
logEntry
},
this
.
environmentService
.
extensionDevelopmentPath
/* target */
);
}
}
private
onError
(
err
:
any
):
void
{
let
errorMessage
=
toErrorMessage
(
err
);
if
(
errorMessage
===
this
.
lastExtensionHostError
)
{
return
;
// prevent error spam
}
this
.
lastExtensionHostError
=
errorMessage
;
this
.
messageService
.
show
(
Severity
.
Error
,
nls
.
localize
(
'
extensionHostProcess.error
'
,
"
Error from the extension host: {0}
"
,
errorMessage
));
}
private
onExit
(
code
:
any
,
signal
:
any
,
onProcessExit
:
any
):
void
{
process
.
removeListener
(
'
exit
'
,
onProcessExit
);
if
(
!
this
.
terminating
)
{
// Unexpected termination
if
(
!
this
.
isExtensionDevelopmentHost
)
{
this
.
messageService
.
show
(
Severity
.
Error
,
{
message
:
nls
.
localize
(
'
extensionHostProcess.crash
'
,
"
Extension host terminated unexpectedly. Please reload the window to recover.
"
),
actions
:
[
this
.
instantiationService
.
createInstance
(
ReloadWindowAction
,
ReloadWindowAction
.
ID
,
ReloadWindowAction
.
LABEL
)]
});
console
.
error
(
'
Extension host terminated unexpectedly. Code:
'
,
code
,
'
Signal:
'
,
signal
);
}
// Expected development extension termination: When the extension host goes down we also shutdown the window
else
if
(
!
this
.
isExtensionDevelopmentTestFromCli
)
{
this
.
windowService
.
getWindow
().
close
();
}
// When CLI testing make sure to exit with proper exit code
else
{
ipc
.
send
(
'
vscode:exit
'
,
code
);
}
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录