|
|
DescriptionWin should call ::TerminateProcess to exit a renderer process
Win should not call _exit(0) because the behavior is odd.
(See more discussion in https://codereview.chromium.org/2309153002/.)
Instead, Win should use ::TerminateProcess.
BUG=639244
Review-Url: https://codereview.chromium.org/2629623003
Cr-Commit-Position: refs/heads/master@{#448916}
Committed: https://chromium.googlesource.com/chromium/src/+/940efb95e8eb38337c4df327792b71dcc2de2d84
Patch Set 1 #Patch Set 2 : temp #
Total comments: 2
Patch Set 3 : temp #
Total comments: 3
Patch Set 4 : temp #Patch Set 5 : temp #Patch Set 6 : temp #
Total comments: 2
Patch Set 7 : temp #Patch Set 8 : temp #
Total comments: 2
Patch Set 9 : temp #Patch Set 10 : temp #
Total comments: 2
Patch Set 11 : temp #
Messages
Total messages: 69 (48 generated)
The CQ bit was checked by haraken@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: win_clang on master.tryserver.chromium.win (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.win/builders/win_clang/builds/...)
The CQ bit was checked by haraken@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
haraken@chromium.org changed reviewers: + primiano@chromium.org, thakis@chromium.org
PTAL
See comments below. Also since the harness is already there (see process_unittest.cc) I'd add a test for this feature. It is quite easy to regress the exit code by refactoring this code, and if we do this one year from now, it might end up silently screwing up our OOM stats. https://codereview.chromium.org/2629623003/diff/20001/base/process/process_po... File base/process/process_posix.cc (right): https://codereview.chromium.org/2629623003/diff/20001/base/process/process_po... base/process/process_posix.cc:354: _exit(0); two things here: 1) s/0/exit_code/ :) 2) note that in the current API Process is an object that can be a remote process, not the current one. The way this is implemented is a bit contra-intuitive beause you can do Process another = Process.Open(...) another.TerminateImmediately() the expectation in this case is that it would terminate immediately the |other| process. Instead this will terminate the current one, leaving everybody amazingly surprised. I think the possible ways to deal with this is: 1) Make this a static method and call it TerminateCurrentProcessImmediately 2) CHECK(is_current()) << "Immediate termination of another process is not a supported use case") 3) Just kill(process_, SIGKILL) (in which case I'd refactor and extract the common code from ::Terminate instead of duplicating) 3 has a small drawback, when you SIGKILL the process will exit immediately, but with an exit code of != 0 (specifically 137 if I did the math correctly). Not sure if this (the fact that a child dies with != 0) will confuse the browser process, letting it kill that the process was killed by an external event (concretely if we have any sort of code that tries to account child processes OOM, this might be confused for a kill due to OOM) Very likely terminating immediately another process is not a use case that we care about, so I would go either for 1 or for 2.
https://codereview.chromium.org/2629623003/diff/20001/base/process/process_po... File base/process/process_posix.cc (right): https://codereview.chromium.org/2629623003/diff/20001/base/process/process_po... base/process/process_posix.cc:354: _exit(0); On 2017/01/13 17:08:17, Primiano Tucci wrote: > two things here: > 1) s/0/exit_code/ :) > 2) note that in the current API Process is an object that can be a remote > process, not the current one. > The way this is implemented is a bit contra-intuitive beause you can do > > Process another = Process.Open(...) > another.TerminateImmediately() > > the expectation in this case is that it would terminate immediately the |other| > process. Instead this will terminate the current one, leaving everybody > amazingly surprised. > > I think the possible ways to deal with this is: > > 1) Make this a static method and call it TerminateCurrentProcessImmediately > 2) CHECK(is_current()) << "Immediate termination of another process is not a > supported use case") > 3) Just kill(process_, SIGKILL) (in which case I'd refactor and extract the > common code from ::Terminate instead of duplicating) > > 3 has a small drawback, when you SIGKILL the process will exit immediately, but > with an exit code of != 0 (specifically 137 if I did the math correctly). Not > sure if this (the fact that a child dies with != 0) will confuse the browser > process, letting it kill that the process was killed by an external event > (concretely if we have any sort of code that tries to account child processes > OOM, this might be confused for a kill due to OOM) > > Very likely terminating immediately another process is not a use case that we > care about, so I would go either for 1 or for 2. Agreed, 1 or 2 seem more appropriate. 1 seems a tiny bit simpler to me, but up to you.
The CQ bit was checked by haraken@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: cast_shell_linux on master.tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/cast_shell_linu...)
On 2017/01/13 17:08:17, Primiano Tucci wrote: > See comments below. > Also since the harness is already there (see process_unittest.cc) I'd add a test > for this feature. It is quite easy to regress the exit code by refactoring this > code, and if we do this one year from now, it might end up silently screwing up > our OOM stats. How can we test TerminateCurrentProcessImmediately? Since it exits the *current* process immediately, we cannot test the behavior by process.TerminateCurrentProcessImmediately() or something. See the patch set 3 -- it doesn't work. > > https://codereview.chromium.org/2629623003/diff/20001/base/process/process_po... > File base/process/process_posix.cc (right): > > https://codereview.chromium.org/2629623003/diff/20001/base/process/process_po... > base/process/process_posix.cc:354: _exit(0); > two things here: > 1) s/0/exit_code/ :) > 2) note that in the current API Process is an object that can be a remote > process, not the current one. > The way this is implemented is a bit contra-intuitive beause you can do > > Process another = Process.Open(...) > another.TerminateImmediately() > > the expectation in this case is that it would terminate immediately the |other| > process. Instead this will terminate the current one, leaving everybody > amazingly surprised. > > I think the possible ways to deal with this is: > > 1) Make this a static method and call it TerminateCurrentProcessImmediately > 2) CHECK(is_current()) << "Immediate termination of another process is not a > supported use case") > 3) Just kill(process_, SIGKILL) (in which case I'd refactor and extract the > common code from ::Terminate instead of duplicating) > > 3 has a small drawback, when you SIGKILL the process will exit immediately, but > with an exit code of != 0 (specifically 137 if I did the math correctly). Not > sure if this (the fact that a child dies with != 0) will confuse the browser > process, letting it kill that the process was killed by an external event > (concretely if we have any sort of code that tries to account child processes > OOM, this might be confused for a kill due to OOM) > > Very likely terminating immediately another process is not a use case that we > care about, so I would go either for 1 or for 2. Adopted 1).
https://codereview.chromium.org/2629623003/diff/40001/base/process/process.h File base/process/process.h (right): https://codereview.chromium.org/2629623003/diff/40001/base/process/process.h#... base/process/process.h:106: void TerminateCurrentProcessImmediately(int exit_code) const; +static (and move up with the other statics) as this does not make sense as a member function https://codereview.chromium.org/2629623003/diff/40001/base/process/process_un... File base/process/process_unittest.cc (right): https://codereview.chromium.org/2629623003/diff/40001/base/process/process_un... base/process/process_unittest.cc:163: process.TerminateCurrentProcessImmediately(kExpectedExitCode); well this is the problem. You don't want to terminate the test_f process, but the child one. concretely I think you need to add a : MULTIPROCESS_TEST_MAIN(TerminateImmediatelyChildProcess) { Process::TerminateCurrentProcessImmediately(kExpectedExitCode); return 0; } and here in this funciton you SpawnChild("TerminateImmediatelyChildProcess") and check that it did exit with kExpectedExitCode https://codereview.chromium.org/2629623003/diff/40001/base/process/process_un... base/process/process_unittest.cc:170: // The POSIX implementation actually ignores the exit_code. Where did this happen? I tried both on OSX and Linux and it seems to be respected.
The CQ bit was checked by haraken@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: cast_shell_linux on master.tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/cast_shell_linu...)
The CQ bit was checked by haraken@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: win_chromium_compile_dbg_ng on master.tryserver.chromium.win (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.win/builders/win_chromium_comp...)
The CQ bit was checked by haraken@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
PTAL
https://codereview.chromium.org/2629623003/diff/100001/base/process/process_u... File base/process/process_unittest.cc (right): https://codereview.chromium.org/2629623003/diff/100001/base/process/process_u... base/process/process_unittest.cc:151: MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediately) { Well this is good but no sufficient. You still need a TEST_F thay uses this, like the one you had in your previous patch set https://codereview.chromium.org/2629623003/diff/100001/content/renderer/rende... File content/renderer/render_thread_impl.cc (right): https://codereview.chromium.org/2629623003/diff/100001/content/renderer/rende... content/renderer/render_thread_impl.cc:951: base::Process::Current().TerminateCurrentProcessImmediately(0); No need for current() here
The CQ bit was checked by haraken@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: mac_chromium_rel_ng on master.tryserver.chromium.mac (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.mac/builders/mac_chromium_rel_...)
The CQ bit was checked by haraken@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
PTAL https://codereview.chromium.org/2629623003/diff/140001/base/process/process_u... File base/process/process_unittest.cc (right): https://codereview.chromium.org/2629623003/diff/140001/base/process/process_u... base/process/process_unittest.cc:174: #if !defined(OS_POSIX) It looks like this guard is needed. In Linux, exit_code is 0 here.
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: Try jobs failed on following builders: win_chromium_rel_ng on master.tryserver.chromium.win (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.win/builders/win_chromium_rel_...)
The CQ bit was checked by haraken@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
https://codereview.chromium.org/2629623003/diff/140001/base/process/process_u... File base/process/process_unittest.cc (right): https://codereview.chromium.org/2629623003/diff/140001/base/process/process_u... base/process/process_unittest.cc:174: #if !defined(OS_POSIX) On 2017/01/17 09:40:27, haraken wrote: > > It looks like this guard is needed. In Linux, exit_code is 0 here. > I insist, on linux the exit code works really fine. The problem is that here you are creating a race because you first wait for the process to exit and then get its termination status. you cannot detect the termination status twice. If you did build this in debug with logging, you would have seen this: [16030:16030:0117/113305.527613:1125986610551:ERROR:kill_posix.cc(34)] waitpid(16031): No child processes so what happens is that you are getting 0 because you make the process go away with the first call to WaitForExitWithTimeout and then you poll a non existing process with GetTerminationStatus. I think you here want to super-simplify this: ----- MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode0) { Process::TerminateCurrentProcessImmediately(0); NOTREACHED(); return 42; } TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithZeroExitCode) { Process process(SpawnChild("TerminateCurrentProcessImmediatelyWithCode0")); ASSERT_TRUE(process.IsValid()); int exit_code = 42; ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(), &exit_code)); EXPECT_EQ(0, exit_code); } MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode250) { Process::TerminateCurrentProcessImmediately(250); NOTREACHED(); return 42; } TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithNonZeroExitCode) { Process process(SpawnChild("TerminateCurrentProcessImmediatelyWithCode250")); ASSERT_TRUE(process.IsValid()); int exit_code = 42; ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(), &exit_code)); EXPECT_EQ(250, exit_code); } ----- I tried this in my linux workstation and it works
On 2017/01/17 12:08:21, Primiano Tucci wrote: > https://codereview.chromium.org/2629623003/diff/140001/base/process/process_u... > File base/process/process_unittest.cc (right): > > https://codereview.chromium.org/2629623003/diff/140001/base/process/process_u... > base/process/process_unittest.cc:174: #if !defined(OS_POSIX) > On 2017/01/17 09:40:27, haraken wrote: > > > > It looks like this guard is needed. In Linux, exit_code is 0 here. > > > > I insist, on linux the exit code works really fine. The problem is that here you > are creating a race because you first wait for the process to exit and then get > its termination status. you cannot detect the termination status twice. > If you did build this in debug with logging, you would have seen this: > [16030:16030:0117/113305.527613:1125986610551:ERROR:kill_posix.cc(34)] > waitpid(16031): No child processes > > so what happens is that you are getting 0 because you make the process go away > with the first call to WaitForExitWithTimeout and then you poll a non existing > process with GetTerminationStatus. > > I think you here want to super-simplify this: > > ----- > MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode0) { > Process::TerminateCurrentProcessImmediately(0); > NOTREACHED(); > return 42; > } > > TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithZeroExitCode) { > Process process(SpawnChild("TerminateCurrentProcessImmediatelyWithCode0")); > ASSERT_TRUE(process.IsValid()); > int exit_code = 42; > ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(), > &exit_code)); > EXPECT_EQ(0, exit_code); > } > > MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode250) { > Process::TerminateCurrentProcessImmediately(250); > NOTREACHED(); > return 42; > } > > TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithNonZeroExitCode) { > Process process(SpawnChild("TerminateCurrentProcessImmediatelyWithCode250")); > ASSERT_TRUE(process.IsValid()); > int exit_code = 42; > ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(), > &exit_code)); > EXPECT_EQ(250, exit_code); > } > ----- > > I tried this in my linux workstation and it works Thanks, done.
The CQ bit was checked by haraken@chromium.org to run a CQ dry run
Dry run: CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
thanks, LGTM
The CQ bit was unchecked by commit-bot@chromium.org
Dry run: This issue passed the CQ dry run.
The CQ bit was checked by haraken@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
The CQ bit was unchecked by commit-bot@chromium.org
Try jobs failed on following builders: chromium_presubmit on master.tryserver.chromium.linux (JOB_FAILED, http://build.chromium.org/p/tryserver.chromium.linux/builders/chromium_presub...)
haraken@chromium.org changed reviewers: + kinuko@chromium.org
thakis@: PTAL at base/ ? kinuko@: rs at renderer/ ?
On 2017/01/19 14:07:41, haraken wrote: > thakis@: PTAL at base/ ? > kinuko@: rs at renderer/ ? renderer change lgtm
thakis@: friendly ping?
base/ lgtm https://codereview.chromium.org/2629623003/diff/180001/base/process/process_u... File base/process/process_unittest.cc (right): https://codereview.chromium.org/2629623003/diff/180001/base/process/process_u... base/process/process_unittest.cc:152: Process::TerminateCurrentProcessImmediately(0); maybe this test should register an atexit handler and check that it's not getting called?
https://codereview.chromium.org/2629623003/diff/180001/base/process/process_u... File base/process/process_unittest.cc (right): https://codereview.chromium.org/2629623003/diff/180001/base/process/process_u... base/process/process_unittest.cc:152: Process::TerminateCurrentProcessImmediately(0); On 2017/02/07 15:19:34, Nico wrote: > maybe this test should register an atexit handler and check that it's not > getting called? oh very good point. I guess you could both: - register an atexithandler with does a CHECK(false): - initialize a ThreadLocalStorage entry with a destructor that does the same to check that neither explicit handlers nor libc/crt handled ones are triggered.
On 2017/02/07 15:48:11, Primiano Tucci wrote: > https://codereview.chromium.org/2629623003/diff/180001/base/process/process_u... > File base/process/process_unittest.cc (right): > > https://codereview.chromium.org/2629623003/diff/180001/base/process/process_u... > base/process/process_unittest.cc:152: > Process::TerminateCurrentProcessImmediately(0); > On 2017/02/07 15:19:34, Nico wrote: > > maybe this test should register an atexit handler and check that it's not > > getting called? > > oh very good point. I guess you could both: > - register an atexithandler with does a CHECK(false): > - initialize a ThreadLocalStorage entry with a destructor that does the same > to check that neither explicit handlers nor libc/crt handled ones are triggered. Done.
The CQ bit was checked by haraken@chromium.org
The patchset sent to the CQ was uploaded after l-g-t-m from primiano@chromium.org, kinuko@chromium.org, thakis@chromium.org Link to the patchset: https://codereview.chromium.org/2629623003/#ps200001 (title: "temp")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/v2/patch-status/codereview.chromium.or...
CQ is committing da patch. Bot data: {"patchset_id": 200001, "attempt_start_ts": 1486527708933170, "parent_rev": "ae9143a9d87c734f5b31f72f296917cc8bc24588", "commit_rev": "940efb95e8eb38337c4df327792b71dcc2de2d84"}
Message was sent while issue was closed.
Description was changed from ========== Win should call ::TerminateProcess to exit a renderer process Win should not call _exit(0) because the behavior is odd. (See more discussion in https://codereview.chromium.org/2309153002/.) Instead, Win should use ::TerminateProcess. BUG=639244 ========== to ========== Win should call ::TerminateProcess to exit a renderer process Win should not call _exit(0) because the behavior is odd. (See more discussion in https://codereview.chromium.org/2309153002/.) Instead, Win should use ::TerminateProcess. BUG=639244 Review-Url: https://codereview.chromium.org/2629623003 Cr-Commit-Position: refs/heads/master@{#448916} Committed: https://chromium.googlesource.com/chromium/src/+/940efb95e8eb38337c4df327792b... ==========
Message was sent while issue was closed.
Committed patchset #11 (id:200001) as https://chromium.googlesource.com/chromium/src/+/940efb95e8eb38337c4df327792b... |