aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/src/zip.erl
diff options
context:
space:
mode:
authorDaniel White <[email protected]>2015-01-17 19:20:41 +1100
committerDaniel White <[email protected]>2015-01-17 19:37:16 +1100
commitaaa7c91756da6eb4435c9a23f4725dcc1dc147aa (patch)
treea1da4bfee9a41fbb95faf01bd8064ea96c8a492b /lib/stdlib/src/zip.erl
parent905824012cef106e7bd3796bff36a2aa04b58850 (diff)
downloadotp-aaa7c91756da6eb4435c9a23f4725dcc1dc147aa.tar.gz
otp-aaa7c91756da6eb4435c9a23f4725dcc1dc147aa.tar.bz2
otp-aaa7c91756da6eb4435c9a23f4725dcc1dc147aa.zip
Prevent zip:zip_open/1,2 from leaking ports
The case was discovered where a parent process would exit before closing the zip file. The result was that a port would be left open indefinitely, as the small zip server would not detect this condition. By comparison, the file module will close the associated port when the parent exits for any reason. This change would make the zip module more consistent with the semantics of similar modules. This change is breaking for any callers expecting to pass the handle to another process for processing (assuming it exits).
Diffstat (limited to 'lib/stdlib/src/zip.erl')
-rw-r--r--lib/stdlib/src/zip.erl26
1 files changed, 17 insertions, 9 deletions
diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl
index b768c6d0b9..cbd326ae92 100644
--- a/lib/stdlib/src/zip.erl
+++ b/lib/stdlib/src/zip.erl
@@ -1114,15 +1114,19 @@ local_file_header_from_info_method_name(#file_info{mtime = MTime},
file_name_length = length(Name),
extra_field_length = 0}.
+server_init(Parent) ->
+ %% we want to know if our parent dies
+ process_flag(trap_exit, true),
+ server_loop(Parent, not_open).
%% small, simple, stupid zip-archive server
-server_loop(OpenZip) ->
+server_loop(Parent, OpenZip) ->
receive
{From, {open, Archive, Options}} ->
case openzip_open(Archive, Options) of
{ok, NewOpenZip} ->
From ! {self(), {ok, self()}},
- server_loop(NewOpenZip);
+ server_loop(Parent, NewOpenZip);
Error ->
From ! {self(), Error}
end;
@@ -1130,19 +1134,22 @@ server_loop(OpenZip) ->
From ! {self(), openzip_close(OpenZip)};
{From, get} ->
From ! {self(), openzip_get(OpenZip)},
- server_loop(OpenZip);
+ server_loop(Parent, OpenZip);
{From, {get, FileName}} ->
From ! {self(), openzip_get(FileName, OpenZip)},
- server_loop(OpenZip);
+ server_loop(Parent, OpenZip);
{From, list_dir} ->
From ! {self(), openzip_list_dir(OpenZip)},
- server_loop(OpenZip);
+ server_loop(Parent, OpenZip);
{From, {list_dir, Opts}} ->
From ! {self(), openzip_list_dir(OpenZip, Opts)},
- server_loop(OpenZip);
+ server_loop(Parent, OpenZip);
{From, get_state} ->
From ! {self(), OpenZip},
- server_loop(OpenZip);
+ server_loop(Parent, OpenZip);
+ {'EXIT', Parent, Reason} ->
+ openzip_close(OpenZip),
+ exit({parent_died, Reason});
_ ->
{error, bad_msg}
end.
@@ -1162,8 +1169,9 @@ zip_open(Archive) -> zip_open(Archive, []).
Reason :: term()).
zip_open(Archive, Options) ->
- Pid = spawn(fun() -> server_loop(not_open) end),
- request(self(), Pid, {open, Archive, Options}).
+ Self = self(),
+ Pid = spawn_link(fun() -> server_init(Self) end),
+ request(Self, Pid, {open, Archive, Options}).
-spec(zip_get(ZipHandle) -> {ok, [Result]} | {error, Reason} when
ZipHandle :: pid(),