comparison src/eval.c @ 8174:f2286ff0c102 v7.4.1380

commit https://github.com/vim/vim/commit/ee1cffc07a42441924c5353af7fd7ab6e97e5aae Author: Bram Moolenaar <Bram@vim.org> Date: Sun Feb 21 19:14:41 2016 +0100 patch 7.4.1380 Problem: The job exit callback is not implemented. Solution: Add the "exit-cb" option.
author Christian Brabandt <cb@256bit.org>
date Sun, 21 Feb 2016 19:15:04 +0100
parents a0ffb1f3dedc
children e77efd7a7dad
comparison
equal deleted inserted replaced
8173:8f9a62af9212 8174:f2286ff0c102
7772 first_job = job->jv_next; 7772 first_job = job->jv_next;
7773 else 7773 else
7774 job->jv_prev->jv_next = job->jv_next; 7774 job->jv_prev->jv_next = job->jv_next;
7775 7775
7776 vim_free(job->jv_stoponexit); 7776 vim_free(job->jv_stoponexit);
7777 vim_free(job->jv_exit_cb);
7777 vim_free(job); 7778 vim_free(job);
7778 } 7779 }
7779 7780
7780 static void 7781 static void
7781 job_unref(job_T *job) 7782 job_unref(job_T *job)
7782 { 7783 {
7783 if (job != NULL && --job->jv_refcount <= 0) 7784 if (job != NULL && --job->jv_refcount <= 0)
7784 job_free(job); 7785 {
7786 /* Do not free the job when it has not ended yet and there is a
7787 * "stoponexit" flag or an exit callback. */
7788 if (job->jv_status != JOB_STARTED
7789 || (job->jv_stoponexit == NULL && job->jv_exit_cb == NULL))
7790 job_free(job);
7791 }
7785 } 7792 }
7786 7793
7787 /* 7794 /*
7788 * Allocate a job. Sets the refcount to one and sets options default. 7795 * Allocate a job. Sets the refcount to one and sets options default.
7789 */ 7796 */
7817 if (opt->jo_stoponexit == NULL || *opt->jo_stoponexit == NUL) 7824 if (opt->jo_stoponexit == NULL || *opt->jo_stoponexit == NUL)
7818 job->jv_stoponexit = NULL; 7825 job->jv_stoponexit = NULL;
7819 else 7826 else
7820 job->jv_stoponexit = vim_strsave(opt->jo_stoponexit); 7827 job->jv_stoponexit = vim_strsave(opt->jo_stoponexit);
7821 } 7828 }
7829 if (opt->jo_set & JO_EXIT_CB)
7830 {
7831 vim_free(job->jv_exit_cb);
7832 if (opt->jo_exit_cb == NULL || *opt->jo_exit_cb == NUL)
7833 job->jv_exit_cb = NULL;
7834 else
7835 job->jv_exit_cb = vim_strsave(opt->jo_exit_cb);
7836 }
7822 } 7837 }
7823 7838
7824 /* 7839 /*
7825 * Called when Vim is exiting: kill all jobs that have the "stoponexit" flag. 7840 * Called when Vim is exiting: kill all jobs that have the "stoponexit" flag.
7826 */ 7841 */
7828 job_stop_on_exit() 7843 job_stop_on_exit()
7829 { 7844 {
7830 job_T *job; 7845 job_T *job;
7831 7846
7832 for (job = first_job; job != NULL; job = job->jv_next) 7847 for (job = first_job; job != NULL; job = job->jv_next)
7833 if (job->jv_stoponexit != NULL && *job->jv_stoponexit != NUL) 7848 if (job->jv_status == JOB_STARTED && job->jv_stoponexit != NULL)
7834 mch_stop_job(job, job->jv_stoponexit); 7849 mch_stop_job(job, job->jv_stoponexit);
7835 } 7850 }
7836 #endif 7851 #endif
7837 7852
7838 static char * 7853 static char *
10028 break; 10043 break;
10029 opt->jo_set |= JO_OUT_CALLBACK; 10044 opt->jo_set |= JO_OUT_CALLBACK;
10030 opt->jo_out_cb = get_callback(item); 10045 opt->jo_out_cb = get_callback(item);
10031 if (opt->jo_out_cb == NULL) 10046 if (opt->jo_out_cb == NULL)
10032 { 10047 {
10033 EMSG2(_(e_invarg2), "out-db"); 10048 EMSG2(_(e_invarg2), "out-cb");
10034 return FAIL; 10049 return FAIL;
10035 } 10050 }
10036 } 10051 }
10037 else if (STRCMP(hi->hi_key, "err-cb") == 0) 10052 else if (STRCMP(hi->hi_key, "err-cb") == 0)
10038 { 10053 {
10103 opt->jo_stoponexit = get_tv_string_buf_chk(item, 10118 opt->jo_stoponexit = get_tv_string_buf_chk(item,
10104 opt->jo_soe_buf); 10119 opt->jo_soe_buf);
10105 if (opt->jo_stoponexit == NULL) 10120 if (opt->jo_stoponexit == NULL)
10106 { 10121 {
10107 EMSG2(_(e_invarg2), "stoponexit"); 10122 EMSG2(_(e_invarg2), "stoponexit");
10123 return FAIL;
10124 }
10125 }
10126 else if (STRCMP(hi->hi_key, "exit-cb") == 0)
10127 {
10128 if (!(supported & JO_EXIT_CB))
10129 break;
10130 opt->jo_set |= JO_EXIT_CB;
10131 opt->jo_exit_cb = get_tv_string_buf_chk(item, opt->jo_ecb_buf);
10132 if (opt->jo_ecb_buf == NULL)
10133 {
10134 EMSG2(_(e_invarg2), "exit-cb");
10108 return FAIL; 10135 return FAIL;
10109 } 10136 }
10110 } 10137 }
10111 else 10138 else
10112 break; 10139 break;
14769 f_items(typval_T *argvars, typval_T *rettv) 14796 f_items(typval_T *argvars, typval_T *rettv)
14770 { 14797 {
14771 dict_list(argvars, rettv, 2); 14798 dict_list(argvars, rettv, 2);
14772 } 14799 }
14773 14800
14774 #ifdef FEAT_JOB 14801 #if defined(FEAT_JOB) || defined(PROTO)
14775 /* 14802 /*
14776 * Get the job from the argument. 14803 * Get the job from the argument.
14777 * Returns NULL if the job is invalid. 14804 * Returns NULL if the job is invalid.
14778 */ 14805 */
14779 static job_T * 14806 static job_T *
14822 jobopt_T opt; 14849 jobopt_T opt;
14823 14850
14824 if (job == NULL) 14851 if (job == NULL)
14825 return; 14852 return;
14826 clear_job_options(&opt); 14853 clear_job_options(&opt);
14827 if (get_job_options(&argvars[1], &opt, JO_STOPONEXIT) == FAIL) 14854 if (get_job_options(&argvars[1], &opt, JO_STOPONEXIT + JO_EXIT_CB) == FAIL)
14828 return; 14855 return;
14829 job_set_options(job, &opt); 14856 job_set_options(job, &opt);
14830 } 14857 }
14831 14858
14832 /* 14859 /*
14856 14883
14857 /* Default mode is NL. */ 14884 /* Default mode is NL. */
14858 clear_job_options(&opt); 14885 clear_job_options(&opt);
14859 opt.jo_mode = MODE_NL; 14886 opt.jo_mode = MODE_NL;
14860 if (get_job_options(&argvars[1], &opt, 14887 if (get_job_options(&argvars[1], &opt,
14861 JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL + JO_STOPONEXIT) == FAIL) 14888 JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL
14889 + JO_STOPONEXIT + JO_EXIT_CB) == FAIL)
14862 return; 14890 return;
14863 job_set_options(job, &opt); 14891 job_set_options(job, &opt);
14864 14892
14865 #ifndef USE_ARGV 14893 #ifndef USE_ARGV
14866 ga_init2(&ga, (int)sizeof(char*), 20); 14894 ga_init2(&ga, (int)sizeof(char*), 20);
14957 vim_free(ga.ga_data); 14985 vim_free(ga.ga_data);
14958 #endif 14986 #endif
14959 } 14987 }
14960 14988
14961 /* 14989 /*
14990 * Get the status of "job" and invoke the exit callback when needed.
14991 * The returned string is not allocated.
14992 */
14993 static char *
14994 job_status(job_T *job)
14995 {
14996 char *result;
14997
14998 if (job->jv_status == JOB_ENDED)
14999 /* No need to check, dead is dead. */
15000 result = "dead";
15001 else if (job->jv_status == JOB_FAILED)
15002 result = "fail";
15003 else
15004 {
15005 result = mch_job_status(job);
15006 # ifdef FEAT_CHANNEL
15007 if (job->jv_status == JOB_ENDED)
15008 ch_log(job->jv_channel, "Job ended");
15009 # endif
15010 if (job->jv_status == JOB_ENDED && job->jv_exit_cb != NULL)
15011 {
15012 typval_T argv[3];
15013 typval_T rettv;
15014 int dummy;
15015
15016 /* invoke the exit callback */
15017 argv[0].v_type = VAR_JOB;
15018 argv[0].vval.v_job = job;
15019 argv[1].v_type = VAR_NUMBER;
15020 argv[1].vval.v_number = job->jv_exitval;
15021 call_func(job->jv_exit_cb, (int)STRLEN(job->jv_exit_cb),
15022 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
15023 clear_tv(&rettv);
15024 }
15025 if (job->jv_status == JOB_ENDED && job->jv_refcount == 0)
15026 {
15027 /* The job already was unreferenced, now that it ended it can be
15028 * freed. Careful: caller must not use "job" after this! */
15029 job_free(job);
15030 }
15031 }
15032 return result;
15033 }
15034
15035 /*
15036 * Called once in a while: check if any jobs with an "exit-cb" have ended.
15037 */
15038 void
15039 job_check_ended()
15040 {
15041 static time_t last_check = 0;
15042 time_t now;
15043 job_T *job;
15044 job_T *next;
15045
15046 /* Only do this once in 10 seconds. */
15047 now = time(NULL);
15048 if (last_check + 10 < now)
15049 {
15050 last_check = now;
15051 for (job = first_job; job != NULL; job = next)
15052 {
15053 next = job->jv_next;
15054 if (job->jv_status == JOB_STARTED && job->jv_exit_cb != NULL)
15055 job_status(job); /* may free "job" */
15056 }
15057 }
15058 }
15059
15060 /*
14962 * "job_status()" function 15061 * "job_status()" function
14963 */ 15062 */
14964 static void 15063 static void
14965 f_job_status(typval_T *argvars, typval_T *rettv) 15064 f_job_status(typval_T *argvars, typval_T *rettv)
14966 { 15065 {
14967 job_T *job = get_job_arg(&argvars[0]); 15066 job_T *job = get_job_arg(&argvars[0]);
14968 char *result; 15067 char *result;
14969 15068
14970 if (job != NULL) 15069 if (job != NULL)
14971 { 15070 {
14972 if (job->jv_status == JOB_ENDED) 15071 result = job_status(job);
14973 /* No need to check, dead is dead. */
14974 result = "dead";
14975 else if (job->jv_status == JOB_FAILED)
14976 result = "fail";
14977 else
14978 result = mch_job_status(job);
14979 rettv->v_type = VAR_STRING; 15072 rettv->v_type = VAR_STRING;
14980 rettv->vval.v_string = vim_strsave((char_u *)result); 15073 rettv->vval.v_string = vim_strsave((char_u *)result);
14981 } 15074 }
14982 } 15075 }
14983 15076
22855 break; 22948 break;
22856 #endif 22949 #endif
22857 case VAR_JOB: 22950 case VAR_JOB:
22858 #ifdef FEAT_JOB 22951 #ifdef FEAT_JOB
22859 to->vval.v_job = from->vval.v_job; 22952 to->vval.v_job = from->vval.v_job;
22860 ++to->vval.v_job->jv_refcount; 22953 if (to->vval.v_job != NULL)
22954 ++to->vval.v_job->jv_refcount;
22861 break; 22955 break;
22862 #endif 22956 #endif
22863 case VAR_CHANNEL: 22957 case VAR_CHANNEL:
22864 #ifdef FEAT_CHANNEL 22958 #ifdef FEAT_CHANNEL
22865 to->vval.v_channel = from->vval.v_channel; 22959 to->vval.v_channel = from->vval.v_channel;