maintenance: disable cron on macOS
PATCH 1/1 maintenance: disable cron on macOS
From: Derrick Stolee <[email protected]>
In eba1ba9 (maintenance: git maintenance run learned --scheduler=<scheduler>, 2021-09-04), we introduced the ability to specify a scheduler explicitly. This led to some extra checks around whether an alternative scheduler was available. This added the functionality of removing background maintenance from schedulers other than the one selected.
On macOS, cron is technically available, but running 'crontab' triggers a UI prompt asking for special permissions. This is the major reason why launchctl is used as the default scheduler. The is_crontab_available() method triggers this UI prompt, causing user disruption.
Remove this disruption by using an #ifdef to prevent running crontab this way on macOS. This has the unfortunate downside that if a user manually selects cron via the '--scheduler' option, then adjusting the scheduler later will not remove the schedule from cron. The '--scheduler' option ignores the is_available checks, which is how we can get into this situation.
Extract the new check_crontab_process() method to avoid making the 'child' variable unused on macOS. The method is marked MAYBE_UNUSED because it has no callers on macOS.
---
[For 2.34.0 Release] maintenance: disable cron on macOS
This one is really tricky because we can't notice anything is wrong without running git maintenance start or git maintenance stop interactively on macOS. The tests pass just fine because the UI alert gets automatically ignored during the test suite.
This is a bit of a half-fix: it avoids the UI alert, but has a corner case of not un-doing the cron schedule if a user manages to select it (under suitable permissions such that it succeeds). For the purpose of the timing of the release, I think this is an appropriate hedge.
Thanks! -Stolee
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1075%2Fderrickstolee%2Fmaintenance-cron-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1075/derrickstolee/maintenance-cron-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1075
builtin/gc.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)
builtin/gc.c +21 -6
@@ -1999,15 +1999,11 @@ static int schtasks_update_schedule(int run_maintenance, int fd)return schtasks_remove_tasks (); } -static int is_crontab_available (void ) +MAYBE_UNUSED +static int check_crontab_process(const char *cmd) { -const char *cmd ="crontab" ; -int is_available;struct child_process child =CHILD_PROCESS_INIT ; -if (get_schedule_cmd (&cmd, &is_available)) -return is_available; -strvec_split (&child.args, cmd);strvec_push (&child.args,"-l" ); child.no_stdin =1 ;
@@ -2022,6 +2018,25 @@ static int is_crontab_available(void)return 1 ; } +static int is_crontab_available (void ) +{ +const char *cmd ="crontab" ; +int is_available; + +if (get_schedule_cmd (&cmd, &is_available)) +return is_available; + +#ifdef __APPLE__ +/* +* macOS has cron, but it requires special permissions and will +* create a UI alert when attempting to run this command. +*/ +return 0 ; +#else +return check_crontab_process (cmd); +#endif +} +#define BEGIN_LINE "# BEGIN GIT MAINTENANCE SCHEDULE"#define END_LINE "# END GIT MAINTENANCE SCHEDULE"
base-commit: 6c220937e2b26d85920bf2d38ff2464a0d57fd6b
Signature · 1 line
gitgitgadget
Hi Stolee,
Quoted 34 lines · Derrick Stolee via GitGitGadget
From: Derrick Stolee <[email protected]>
In eba1ba9 (maintenance:
git maintenance runlearned--scheduler=<scheduler>, 2021-09-04), we introduced the ability to specify a scheduler explicitly. This led to some extra checks around whether an alternative scheduler was available. This added the functionality of removing background maintenance from schedulers other than the one selected.On macOS, cron is technically available, but running 'crontab' triggers a UI prompt asking for special permissions. This is the major reason why launchctl is used as the default scheduler. The
is_crontab_available()method triggers this UI prompt, causing user disruption.Remove this disruption by using an #ifdef to prevent running crontab this way on macOS. This has the unfortunate downside that if a user manually selects cron via the '--scheduler' option, then adjusting the scheduler later will not remove the schedule from cron. The '--scheduler' option ignores the
is_availablechecks, which is how we can get into this situation.Extract the new
check_crontab_process()method to avoid making the 'child' variable unused on macOS. The method is markedMAYBE_UNUSEDbecause it has no callers on macOS.Signed-off-by Derrick Stolee <[email protected]>---
[For 2.34.0 Release] maintenance: disable cron on macOSThis one is really tricky because we can't notice anything is wrong without running git maintenance start or git maintenance stop interactively on macOS. The tests pass just fine because the UI alert gets automatically ignored during the test suite.
Quoted 4 lines
This is a bit of a half-fix: it avoids the UI alert, but has a corner case of not un-doing the cron schedule if a user manages to select it (under suitable permissions such that it succeeds). For the purpose of the timing of the release, I think this is an appropriate hedge.
I agree.
We can revisit this once v2.34.0 is released, and then determine a better layer to prevent this, or alternatively warn very loudly about it.
Thanks,
Dscho
Quoted 64 lines
Thanks! -Stolee
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1075%2Fderrickstolee%2Fmaintenance-cron-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1075/derrickstolee/maintenance-cron-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1075builtin/gc.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)builtin/gc.c +21
-6@@ -1999,15 +1999,11 @@ static int schtasks_update_schedule(int run_maintenance, int fd)return schtasks_remove_tasks (); } -static int is_crontab_available (void ) +MAYBE_UNUSED +static int check_crontab_process(const char *cmd) { -const char *cmd ="crontab" ; -int is_available;struct child_process child =CHILD_PROCESS_INIT ; -if (get_schedule_cmd (&cmd, &is_available)) -return is_available; -strvec_split (&child.args, cmd);strvec_push (&child.args,"-l" ); child.no_stdin =1 ;@@ -2022,6 +2018,25 @@ static int is_crontab_available(void)return 1 ; } +static int is_crontab_available (void ) +{ +const char *cmd ="crontab" ; +int is_available; + +if (get_schedule_cmd (&cmd, &is_available)) +return is_available; + +#ifdef __APPLE__ +/* +* macOS has cron, but it requires special permissions and will +* create a UI alert when attempting to run this command. +*/ +return 0 ; +#else +return check_crontab_process (cmd); +#endif +} +#define BEGIN_LINE "# BEGIN GIT MAINTENANCE SCHEDULE"#define END_LINE "# END GIT MAINTENANCE SCHEDULE"base-commit:
6c220937e2b26d85920bf2d38ff2464a0d57fd6b--
gitgitgadget
Quoted 9 lines · Derrick Stolee via GitGitGadget
This one is really tricky because we can't notice anything is wrong without running git maintenance start or git maintenance stop interactively on macOS. The tests pass just fine because the UI alert gets automatically ignored during the test suite.
This is a bit of a half-fix: it avoids the UI alert, but has a corner case of not un-doing the cron schedule if a user manages to select it (under suitable permissions such that it succeeds). For the purpose of the timing of the release, I think this is an appropriate hedge.
Reverting the "git maintainance run --scheduler=<scheduler>" topic altogether to give us time to stop and think may be another obvious option, but it probably is OK to tell macOS users that they may have cron but Git won't work with their cron with this patch.
In any case, let's leave it (slightly) broken for macOS folks by applying this quickfix.
Thanks.
PS.
I was puzzled by the lack of a call to validate_scheduler() at the very beginning of resolve_scheduler(), by the way. Or even earlier during the verification of the command line options. I wonder if on macOS, --scheduler=nosuch and --scheduler=cron should behave the same way, both saying "unrecognized", instead of saying that only to the former and "not available" to the latter.
Quoted 12 lines · Junio C Hamano
Quoted 9 lines · Derrick Stolee via GitGitGadget
This one is really tricky because we can't notice anything is wrong without running git maintenance start or git maintenance stop interactively on macOS. The tests pass just fine because the UI alert gets automatically ignored during the test suite.
This is a bit of a half-fix: it avoids the UI alert, but has a corner case of not un-doing the cron schedule if a user manages to select it (under suitable permissions such that it succeeds). For the purpose of the timing of the release, I think this is an appropriate hedge.
Quoted 7 lines
Reverting the "git maintainance run --scheduler=<scheduler>" topic altogether to give us time to stop and think may be another obvious option, but it probably is OK to tell macOS users that they may have cron but Git won't work with their cron with this patch.
In any case, let's leave it (slightly) broken for macOS folks by applying this quickfix.
I agree that we don't need to revert the topic.
Quoted 6 lines
I was puzzled by the lack of a call to
validate_scheduler()at the very beginning ofresolve_scheduler(), by the way. Or even earlier during the verification of the command line options. I wonder if on macOS, --scheduler=nosuch and --scheduler=cron should behave the same way, both saying "unrecognized", instead of saying that only to the former and "not available" to the latter.
It's a bit strange, but the crux is that selecting --scheduler=X makes the 'X' scheduler pass through the 'enable' path, while the rest of the "available" schedulers goes through the 'disable' path.
This UI prompt occurs because we are trying to 'disable' cron before enabling launchctl.
I think the biggest issue is how macOS uses non-standard ways of requesting user permissions, because if 'crontab' simply exited with a non-zero status, there would be no work to do here. Because of that, I think we will always need to tiptoe around cron on macOS.
Thanks,
-Stolee
Quoted 97 lines · Derrick Stolee via GitGitGadget
From: Derrick Stolee <[email protected]>
In eba1ba9 (maintenance:
git maintenance runlearned--scheduler=<scheduler>, 2021-09-04), we introduced the ability to specify a scheduler explicitly. This led to some extra checks around whether an alternative scheduler was available. This added the functionality of removing background maintenance from schedulers other than the one selected.On macOS, cron is technically available, but running 'crontab' triggers a UI prompt asking for special permissions. This is the major reason why launchctl is used as the default scheduler. The
is_crontab_available()method triggers this UI prompt, causing user disruption.Remove this disruption by using an #ifdef to prevent running crontab this way on macOS. This has the unfortunate downside that if a user manually selects cron via the '--scheduler' option, then adjusting the scheduler later will not remove the schedule from cron. The '--scheduler' option ignores the
is_availablechecks, which is how we can get into this situation.Extract the new
check_crontab_process()method to avoid making the 'child' variable unused on macOS. The method is markedMAYBE_UNUSEDbecause it has no callers on macOS.Signed-off-by Derrick Stolee <[email protected]>---
[For 2.34.0 Release] maintenance: disable cron on macOSThis one is really tricky because we can't notice anything is wrong without running git maintenance start or git maintenance stop interactively on macOS. The tests pass just fine because the UI alert gets automatically ignored during the test suite.
This is a bit of a half-fix: it avoids the UI alert, but has a corner case of not un-doing the cron schedule if a user manages to select it (under suitable permissions such that it succeeds). For the purpose of the timing of the release, I think this is an appropriate hedge.
Thanks! -Stolee
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1075%2Fderrickstolee%2Fmaintenance-cron-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1075/derrickstolee/maintenance-cron-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1075builtin/gc.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-)builtin/gc.c +21
-6@@ -1999,15 +1999,11 @@ static int schtasks_update_schedule(int run_maintenance, int fd)return schtasks_remove_tasks (); } -static int is_crontab_available (void ) +MAYBE_UNUSED +static int check_crontab_process(const char *cmd) { -const char *cmd ="crontab" ; -int is_available;struct child_process child =CHILD_PROCESS_INIT ; -if (get_schedule_cmd (&cmd, &is_available)) -return is_available; -strvec_split (&child.args, cmd);strvec_push (&child.args,"-l" ); child.no_stdin =1 ;@@ -2022,6 +2018,25 @@ static int is_crontab_available(void)return 1 ; } +static int is_crontab_available (void ) +{ +const char *cmd ="crontab" ; +int is_available; + +if (get_schedule_cmd (&cmd, &is_available)) +return is_available; + +#ifdef __APPLE__ +/* +* macOS has cron, but it requires special permissions and will +* create a UI alert when attempting to run this command. +*/ +return 0 ; +#else +return check_crontab_process (cmd); +#endif +} +#define BEGIN_LINE "# BEGIN GIT MAINTENANCE SCHEDULE"#define END_LINE "# END GIT MAINTENANCE SCHEDULE"
Quoted 1 line
base-commit:
6c220937e2b26d85920bf2d38ff2464a0d57fd6b
I haven't tested, but isn't a smaller fix for this to just re-arrange the array where we declare the methods to check to have "cron" come after all the OS-specific ones, or at least after launchctl?
I.e. we already have an ifdef to pick launchctl and never cron for OSX on "start", so this is only for the case where we loop through the array looking for something to select.
That wouldn't work if that user can run cron, but can't use launchctl at all, but in that case won't they be happy to get the prompt?
Quoted 11 lines · Ævar Arnfjörð Bjarmason
Quoted 8 lines · Derrick Stolee via GitGitGadget
From: Derrick Stolee <[email protected]>
In eba1ba9 (maintenance:
git maintenance runlearned--scheduler=<scheduler>, 2021-09-04), we introduced the ability to specify a scheduler explicitly. This led to some extra checks around whether an alternative scheduler was available. This added the functionality of removing background maintenance from schedulers other than the one selected.
Note this last sentence.
Quoted 10 lines
I haven't tested, but isn't a smaller fix for this to just re-arrange the array where we declare the methods to check to have "cron" come after all the OS-specific ones, or at least after launchctl?
I.e. we already have an ifdef to pick launchctl and never cron for OSX on "start", so this is only for the case where we loop through the array looking for something to select.
That wouldn't work if that user can run cron, but can't use launchctl at all, but in that case won't they be happy to get the prompt?
Your suggestion doesn't work because this isn't about picking cron over launchctl, it's about disabling cron (and systemd or whatever is available) when launchctl was selected.
Thanks,
-Stolee