Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
6ca76333
L
libvirt
项目概览
openeuler
/
libvirt
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
libvirt
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
6ca76333
编写于
5月 09, 2008
作者:
D
David L. Leskovec
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
*** empty log message ***
上级
d9691ab2
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
132 addition
and
43 deletion
+132
-43
ChangeLog
ChangeLog
+5
-0
src/lxc_driver.c
src/lxc_driver.c
+127
-43
未找到文件。
ChangeLog
浏览文件 @
6ca76333
Thu May 9 00:07:34 PST 2008 David L. Leskovec <dlesko@linux.vnet.ibm.com>
* src/lxc_driver.c: use epoll in tty process to avoid consuming the
cpu when the slave side disconnects
Thu May 8 10:36:11 EST 2008 Daniel P. Berrange <berrange@redhat.com>
* HACKING: Added notes on string/memory/buffer internal APIs
...
...
src/lxc_driver.c
浏览文件 @
6ca76333
...
...
@@ -26,9 +26,10 @@
#ifdef WITH_LXC
#include <fcntl.h>
#include <poll.h>
#include <
sys/e
poll.h>
#include <sched.h>
#include <sys/utsname.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <termios.h>
...
...
@@ -552,7 +553,7 @@ static int lxcSetupContainerTty(virConnectPtr conn,
int
rc
=
-
1
;
char
tempTtyName
[
PATH_MAX
];
*
ttymaster
=
posix_openpt
(
O_RDWR
|
O_NOCTTY
);
*
ttymaster
=
posix_openpt
(
O_RDWR
|
O_NOCTTY
|
O_NONBLOCK
);
if
(
*
ttymaster
<
0
)
{
lxcError
(
conn
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"posix_openpt failed: %s"
),
strerror
(
errno
));
...
...
@@ -592,76 +593,156 @@ cleanup:
return
rc
;
}
/**
* lxcFdForward:
* @readFd: file descriptor to read
* @writeFd: file desriptor to write
*
* Reads 1 byte of data from readFd and writes to writeFd.
*
* Returns 0 on success, EAGAIN if returned on read, or -1 in case of error
*/
static
int
lxcFdForward
(
int
readFd
,
int
writeFd
)
{
int
rc
=
-
1
;
char
buf
[
2
];
if
(
1
!=
(
saferead
(
readFd
,
buf
,
1
)))
{
if
(
EAGAIN
==
errno
)
{
rc
=
EAGAIN
;
goto
cleanup
;
}
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"read of fd %d failed: %s"
),
readFd
,
strerror
(
errno
));
goto
cleanup
;
}
if
(
1
!=
(
safewrite
(
writeFd
,
buf
,
1
)))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"write to fd %d failed: %s"
),
writeFd
,
strerror
(
errno
));
goto
cleanup
;
}
rc
=
0
;
cleanup:
return
rc
;
}
typedef
struct
_lxcTtyForwardFd_t
{
int
fd
;
bool
active
;
}
lxcTtyForwardFd_t
;
/**
* lxcTtyForward:
* @fd1: Open fd
* @fd1: Open fd
*
* Forwards traffic between fds. Data read from fd1 will be written to fd2
* Data read from fd2 will be written to fd1. This process loops forever.
* This process loops forever.
* This uses epoll in edge triggered mode to avoid a hard loop on POLLHUP
* events when the user disconnects the virsh console via ctrl-]
*
* Returns 0 on success or -1 in case of error
*/
static
int
lxcTtyForward
(
int
fd1
,
int
fd2
)
{
int
rc
=
-
1
;
int
i
;
char
buf
[
2
];
struct
pollfd
fds
[
2
];
int
numFds
=
0
;
if
(
0
<=
fd1
)
{
fds
[
numFds
].
fd
=
fd1
;
fds
[
numFds
].
events
=
POLLIN
;
++
numFds
;
int
epollFd
;
struct
epoll_event
epollEvent
;
int
numEvents
;
int
numActive
=
0
;
lxcTtyForwardFd_t
fdArray
[
2
];
int
timeout
=
-
1
;
int
curFdOff
=
0
;
int
writeFdOff
=
0
;
fdArray
[
0
].
fd
=
fd1
;
fdArray
[
0
].
active
=
false
;
fdArray
[
1
].
fd
=
fd2
;
fdArray
[
1
].
active
=
false
;
/* create the epoll fild descriptor */
epollFd
=
epoll_create
(
2
);
if
(
0
>
epollFd
)
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"epoll_create(2) failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
}
if
(
0
<=
fd2
)
{
fds
[
numFds
].
fd
=
fd2
;
fds
[
numFds
].
events
=
POLLIN
;
++
numFds
;
/* add the file descriptors the epoll fd */
memset
(
&
epollEvent
,
0x00
,
sizeof
(
epollEvent
));
epollEvent
.
events
=
EPOLLIN
|
EPOLLET
;
/* edge triggered */
epollEvent
.
data
.
fd
=
fd1
;
epollEvent
.
data
.
u32
=
0
;
/* fdArray position */
if
(
0
>
epoll_ctl
(
epollFd
,
EPOLL_CTL_ADD
,
fd1
,
&
epollEvent
))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"epoll_ctl(fd1) failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
}
if
(
0
==
numFds
)
{
DEBUG0
(
"No fds to monitor, return"
);
epollEvent
.
data
.
fd
=
fd2
;
epollEvent
.
data
.
u32
=
1
;
/* fdArray position */
if
(
0
>
epoll_ctl
(
epollFd
,
EPOLL_CTL_ADD
,
fd2
,
&
epollEvent
))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"epoll_ctl(fd2) failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
}
while
(
1
)
{
if
((
rc
=
poll
(
fds
,
numFds
,
-
1
))
<=
0
)
{
/* if active fd's, return if no events, else wait forever */
timeout
=
(
numActive
>
0
)
?
0
:
-
1
;
numEvents
=
epoll_wait
(
epollFd
,
&
epollEvent
,
1
,
timeout
);
if
(
0
<
numEvents
)
{
if
(
epollEvent
.
events
&
EPOLLIN
)
{
curFdOff
=
epollEvent
.
data
.
u32
;
if
(
!
fdArray
[
curFdOff
].
active
)
{
fdArray
[
curFdOff
].
active
=
true
;
++
numActive
;
}
if
((
0
==
rc
)
||
(
errno
==
EINTR
)
||
(
errno
==
EAGAIN
))
{
}
else
if
(
epollEvent
.
events
&
EPOLLHUP
)
{
DEBUG
(
"EPOLLHUP from fd %d"
,
epollEvent
.
data
.
fd
);
continue
;
}
else
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"error event %d"
),
epollEvent
.
events
);
goto
cleanup
;
}
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"poll returned error: %s"
),
strerror
(
errno
));
goto
cleanup
;
}
}
else
if
(
0
==
numEvents
)
{
if
(
2
==
numActive
)
{
/* both fds active, toggle between the two */
curFdOff
^=
1
;
}
else
{
/* only one active, if current is active, use it, else it */
/* must be the other one (ie. curFd just went inactive) */
curFdOff
=
fdArray
[
curFdOff
].
active
?
curFdOff
:
curFdOff
^
1
;
}
for
(
i
=
0
;
i
<
numFds
;
++
i
)
{
if
(
!
fds
[
i
].
revents
)
{
}
else
{
if
(
EINTR
==
errno
)
{
continue
;
}
if
(
fds
[
i
].
revents
&
POLLIN
)
{
if
(
1
!=
(
saferead
(
fds
[
i
].
fd
,
buf
,
1
)))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"read of fd %d failed: %s"
),
i
,
strerror
(
errno
));
goto
cleanup
;
}
/* error */
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"epoll_wait() failed: %s"
),
strerror
(
errno
));
goto
cleanup
;
if
(
1
<
numFds
)
{
if
(
1
!=
(
safewrite
(
fds
[
i
^
1
].
fd
,
buf
,
1
)))
{
lxcError
(
NULL
,
NULL
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"write to fd %d failed: %s"
),
i
,
strerror
(
errno
));
goto
cleanup
;
}
}
}
if
(
0
<
numActive
)
{
writeFdOff
=
curFdOff
^
1
;
rc
=
lxcFdForward
(
fdArray
[
curFdOff
].
fd
,
fdArray
[
writeFdOff
].
fd
);
if
(
EAGAIN
==
rc
)
{
/* this fd no longer has data, set it as inactive */
--
numActive
;
fdArray
[
curFdOff
].
active
=
false
;
}
else
if
(
-
1
==
rc
)
{
goto
cleanup
;
}
}
...
...
@@ -671,7 +752,10 @@ static int lxcTtyForward(int fd1, int fd2)
rc
=
0
;
cleanup:
return
rc
;
close
(
fd1
);
close
(
fd2
);
close
(
epollFd
);
exit
(
rc
);
}
/**
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录