Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
e4d234a2
Unverified
Commit
e4d234a2
authored
Sep 13, 2017
by
Christian Brauner
Committed by
Stéphane Graber
Sep 24, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
utils: fix lxc_popen()/lxc_pclose()
- rework and fix pipe fd leak Signed-off-by:
Christian Brauner
<
christian.brauner@ubuntu.com
>
parent
4443ee50
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
62 additions
and
108 deletions
+62
-108
utils.c
src/lxc/utils.c
+61
-108
utils.h
src/lxc/utils.h
+1
-0
No files found.
src/lxc/utils.c
View file @
e4d234a2
...
@@ -470,152 +470,105 @@ const char** lxc_va_arg_list_to_argv_const(va_list ap, size_t skip)
...
@@ -470,152 +470,105 @@ const char** lxc_va_arg_list_to_argv_const(va_list ap, size_t skip)
return
(
const
char
**
)
lxc_va_arg_list_to_argv
(
ap
,
skip
,
0
);
return
(
const
char
**
)
lxc_va_arg_list_to_argv
(
ap
,
skip
,
0
);
}
}
extern
struct
lxc_popen_FILE
*
lxc_popen
(
const
char
*
command
)
struct
lxc_popen_FILE
*
lxc_popen
(
const
char
*
command
)
{
{
int
ret
;
int
ret
;
struct
lxc_popen_FILE
*
fp
=
NULL
;
int
parent_end
=
-
1
,
child_end
=
-
1
;
int
pipe_fds
[
2
];
int
pipe_fds
[
2
];
pid_t
child_pid
;
pid_t
child_pid
;
struct
lxc_popen_FILE
*
fp
=
NULL
;
int
r
=
pipe2
(
pipe_fds
,
O_CLOEXEC
);
ret
=
pipe2
(
pipe_fds
,
O_CLOEXEC
);
if
(
ret
<
0
)
if
(
r
<
0
)
{
ERROR
(
"pipe2 failure"
);
return
NULL
;
return
NULL
;
}
parent_end
=
pipe_fds
[
0
];
child_end
=
pipe_fds
[
1
];
child_pid
=
fork
();
child_pid
=
fork
();
if
(
child_pid
<
0
)
goto
on_error
;
if
(
child_pid
==
0
)
{
if
(
!
child_pid
)
{
/* child */
sigset_t
mask
;
close
(
parent_end
);
if
(
child_end
!=
STDOUT_FILENO
)
{
close
(
pipe_fds
[
0
]);
/* dup2() doesn't dup close-on-exec flag */
ret
=
dup2
(
child_end
,
STDOUT_FILENO
);
if
(
ret
<
0
)
WARN
(
"Failed to duplicate stdout fd"
);
}
else
{
/*
* The descriptor is already the one we will use.
* But it must not be marked close-on-exec.
* Undo the effects.
*/
ret
=
fcntl
(
child_end
,
F_SETFD
,
0
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to remove FD_CLOEXEC from fd."
);
exit
(
127
);
}
}
if
(
child_end
!=
STDERR_FILENO
)
{
/* duplicate stdout */
/* dup2() doesn't dup close-on-exec flag */
if
(
pipe_fds
[
1
]
!=
STDOUT_FILENO
)
ret
=
dup2
(
child_end
,
STDERR_FILENO
);
ret
=
dup2
(
pipe_fds
[
1
],
STDOUT_FILENO
);
if
(
ret
<
0
)
else
WARN
(
"Failed to duplicate stdout fd"
);
ret
=
fcntl
(
pipe_fds
[
1
],
F_SETFD
,
0
);
}
else
{
if
(
ret
<
0
)
{
/*
close
(
pipe_fds
[
1
]);
* The descriptor is already the one we will use.
exit
(
EXIT_FAILURE
);
* But it must not be marked close-on-exec.
* Undo the effects.
*/
ret
=
fcntl
(
child_end
,
F_SETFD
,
0
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to remove FD_CLOEXEC from fd."
);
exit
(
127
);
}
}
/*
* Unblock signals.
* This is the main/only reason
* why we do our lousy popen() emulation.
*/
{
sigset_t
mask
;
sigfillset
(
&
mask
);
sigprocmask
(
SIG_UNBLOCK
,
&
mask
,
NULL
);
}
}
execl
(
"/bin/sh"
,
"sh"
,
"-c"
,
command
,
(
char
*
)
NULL
);
/* duplicate stderr */
exit
(
127
);
if
(
pipe_fds
[
1
]
!=
STDERR_FILENO
)
}
ret
=
dup2
(
pipe_fds
[
1
],
STDERR_FILENO
);
else
ret
=
fcntl
(
pipe_fds
[
1
],
F_SETFD
,
0
);
close
(
pipe_fds
[
1
]);
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
/* parent */
/* unblock all signals */
ret
=
sigfillset
(
&
mask
);
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
close
(
child_end
);
ret
=
sigprocmask
(
SIG_UNBLOCK
,
&
mask
,
NULL
);
if
(
ret
<
0
)
exit
(
EXIT_FAILURE
);
if
(
child_pid
<
0
)
{
execl
(
"/bin/sh"
,
"sh"
,
"-c"
,
command
,
(
char
*
)
NULL
);
ERROR
(
"fork failure"
);
exit
(
127
);
goto
error
;
}
}
fp
=
calloc
(
1
,
sizeof
(
*
fp
));
close
(
pipe_fds
[
1
]);
if
(
!
fp
)
{
pipe_fds
[
1
]
=
-
1
;
ERROR
(
"failed to allocate memory"
);
goto
error
;
}
fp
->
f
=
fdopen
(
parent_end
,
"r"
);
fp
=
malloc
(
sizeof
(
*
fp
));
if
(
!
fp
->
f
)
{
if
(
!
fp
)
ERROR
(
"fdopen failure"
);
goto
on_error
;
goto
error
;
}
fp
->
child_pid
=
child_pid
;
fp
->
child_pid
=
child_pid
;
fp
->
pipe
=
pipe_fds
[
0
];
return
fp
;
fp
->
f
=
fdopen
(
pipe_fds
[
0
],
"r"
)
;
if
(
!
fp
->
f
)
error
:
goto
on_error
;
if
(
fp
)
{
return
fp
;
if
(
fp
->
f
)
{
fclose
(
fp
->
f
);
parent_end
=
-
1
;
/* so we do not close it second time */
}
on_error
:
if
(
fp
)
free
(
fp
);
free
(
fp
);
}
if
(
parent_end
!=
-
1
)
if
(
pipe_fds
[
0
]
>=
0
)
close
(
parent_end
);
close
(
pipe_fds
[
0
]);
if
(
pipe_fds
[
1
]
>=
0
)
close
(
pipe_fds
[
1
]);
return
NULL
;
return
NULL
;
}
}
extern
int
lxc_pclose
(
struct
lxc_popen_FILE
*
fp
)
int
lxc_pclose
(
struct
lxc_popen_FILE
*
fp
)
{
{
FILE
*
f
=
NULL
;
pid_t
child_pid
=
0
;
int
wstatus
=
0
;
pid_t
wait_pid
;
pid_t
wait_pid
;
int
wstatus
=
0
;
if
(
fp
)
{
if
(
!
fp
)
f
=
fp
->
f
;
child_pid
=
fp
->
child_pid
;
/* free memory (we still need to close file stream) */
free
(
fp
);
fp
=
NULL
;
}
if
(
!
f
||
fclose
(
f
))
{
ERROR
(
"fclose failure"
);
return
-
1
;
return
-
1
;
}
do
{
do
{
wait_pid
=
waitpid
(
child_pid
,
&
wstatus
,
0
);
wait_pid
=
waitpid
(
fp
->
child_pid
,
&
wstatus
,
0
);
}
while
(
wait_pid
==
-
1
&&
errno
==
EINTR
);
}
while
(
wait_pid
<
0
&&
errno
==
EINTR
);
close
(
fp
->
pipe
);
fclose
(
fp
->
f
);
free
(
fp
);
if
(
wait_pid
==
-
1
)
{
if
(
wait_pid
<
0
)
ERROR
(
"waitpid failure"
);
return
-
1
;
return
-
1
;
}
return
wstatus
;
return
wstatus
;
}
}
...
...
src/lxc/utils.h
View file @
e4d234a2
...
@@ -190,6 +190,7 @@ static inline int signalfd(int fd, const sigset_t *mask, int flags)
...
@@ -190,6 +190,7 @@ static inline int signalfd(int fd, const sigset_t *mask, int flags)
* without additional wrappers.
* without additional wrappers.
*/
*/
struct
lxc_popen_FILE
{
struct
lxc_popen_FILE
{
int
pipe
;
FILE
*
f
;
FILE
*
f
;
pid_t
child_pid
;
pid_t
child_pid
;
};
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment