Mercurial > vim
comparison src/channel.c @ 8859:03250bc0c63a v7.4.1717
commit https://github.com/vim/vim/commit/0e4c1de5560c7f8b4cae539ec8cff0949daba3fc
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Apr 7 21:40:38 2016 +0200
patch 7.4.1717
Problem: Leaking memory when opening a channel fails.
Solution: Unreference partials in job options.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 07 Apr 2016 21:45:05 +0200 |
parents | 176647a751d7 |
children | e1b84109506a |
comparison
equal
deleted
inserted
replaced
8858:593b17f02b78 | 8859:03250bc0c63a |
---|---|
856 char_u *address; | 856 char_u *address; |
857 char_u *p; | 857 char_u *p; |
858 char *rest; | 858 char *rest; |
859 int port; | 859 int port; |
860 jobopt_T opt; | 860 jobopt_T opt; |
861 channel_T *channel; | 861 channel_T *channel = NULL; |
862 | 862 |
863 address = get_tv_string(&argvars[0]); | 863 address = get_tv_string(&argvars[0]); |
864 if (argvars[1].v_type != VAR_UNKNOWN | 864 if (argvars[1].v_type != VAR_UNKNOWN |
865 && (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL)) | 865 && (argvars[1].v_type != VAR_DICT || argvars[1].vval.v_dict == NULL)) |
866 { | 866 { |
888 clear_job_options(&opt); | 888 clear_job_options(&opt); |
889 opt.jo_mode = MODE_JSON; | 889 opt.jo_mode = MODE_JSON; |
890 opt.jo_timeout = 2000; | 890 opt.jo_timeout = 2000; |
891 if (get_job_options(&argvars[1], &opt, | 891 if (get_job_options(&argvars[1], &opt, |
892 JO_MODE_ALL + JO_CB_ALL + JO_WAITTIME + JO_TIMEOUT_ALL) == FAIL) | 892 JO_MODE_ALL + JO_CB_ALL + JO_WAITTIME + JO_TIMEOUT_ALL) == FAIL) |
893 return NULL; | 893 goto theend; |
894 if (opt.jo_timeout < 0) | 894 if (opt.jo_timeout < 0) |
895 { | 895 { |
896 EMSG(_(e_invarg)); | 896 EMSG(_(e_invarg)); |
897 return NULL; | 897 goto theend; |
898 } | 898 } |
899 | 899 |
900 channel = channel_open((char *)address, port, opt.jo_waittime, NULL); | 900 channel = channel_open((char *)address, port, opt.jo_waittime, NULL); |
901 if (channel != NULL) | 901 if (channel != NULL) |
902 { | 902 { |
903 opt.jo_set = JO_ALL; | 903 opt.jo_set = JO_ALL; |
904 channel_set_options(channel, &opt); | 904 channel_set_options(channel, &opt); |
905 } | 905 } |
906 theend: | |
907 free_job_options(&opt); | |
906 return channel; | 908 return channel; |
907 } | 909 } |
908 | 910 |
909 static void | 911 static void |
910 may_close_part(sock_T *fd) | 912 may_close_part(sock_T *fd) |
2895 rettv->vval.v_string = NULL; | 2897 rettv->vval.v_string = NULL; |
2896 | 2898 |
2897 clear_job_options(&opt); | 2899 clear_job_options(&opt); |
2898 if (get_job_options(&argvars[1], &opt, JO_TIMEOUT + JO_PART + JO_ID) | 2900 if (get_job_options(&argvars[1], &opt, JO_TIMEOUT + JO_PART + JO_ID) |
2899 == FAIL) | 2901 == FAIL) |
2900 return; | 2902 goto theend; |
2901 | 2903 |
2902 channel = get_channel_arg(&argvars[0], TRUE); | 2904 channel = get_channel_arg(&argvars[0], TRUE); |
2903 if (channel != NULL) | 2905 if (channel != NULL) |
2904 { | 2906 { |
2905 if (opt.jo_set & JO_PART) | 2907 if (opt.jo_set & JO_PART) |
2928 rettv->v_type = VAR_SPECIAL; | 2930 rettv->v_type = VAR_SPECIAL; |
2929 rettv->vval.v_number = VVAL_NONE; | 2931 rettv->vval.v_number = VVAL_NONE; |
2930 } | 2932 } |
2931 } | 2933 } |
2932 } | 2934 } |
2935 | |
2936 theend: | |
2937 free_job_options(&opt); | |
2933 } | 2938 } |
2934 | 2939 |
2935 # if defined(WIN32) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \ | 2940 # if defined(WIN32) || defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) \ |
2936 || defined(PROTO) | 2941 || defined(PROTO) |
2937 /* | 2942 /* |
3054 int *part_read) | 3059 int *part_read) |
3055 { | 3060 { |
3056 channel_T *channel; | 3061 channel_T *channel; |
3057 int part_send; | 3062 int part_send; |
3058 | 3063 |
3064 clear_job_options(opt); | |
3059 channel = get_channel_arg(&argvars[0], TRUE); | 3065 channel = get_channel_arg(&argvars[0], TRUE); |
3060 if (channel == NULL) | 3066 if (channel == NULL) |
3061 return NULL; | 3067 return NULL; |
3062 part_send = channel_part_send(channel); | 3068 part_send = channel_part_send(channel); |
3063 *part_read = channel_part_read(channel); | 3069 *part_read = channel_part_read(channel); |
3064 | 3070 |
3065 clear_job_options(opt); | |
3066 if (get_job_options(&argvars[2], opt, JO_CALLBACK + JO_TIMEOUT) == FAIL) | 3071 if (get_job_options(&argvars[2], opt, JO_CALLBACK + JO_TIMEOUT) == FAIL) |
3067 return NULL; | 3072 return NULL; |
3068 | 3073 |
3069 /* Set the callback. An empty callback means no callback and not reading | 3074 /* Set the callback. An empty callback means no callback and not reading |
3070 * the response. With "ch_evalexpr()" and "ch_evalraw()" a callback is not | 3075 * the response. With "ch_evalexpr()" and "ch_evalraw()" a callback is not |
3143 *rettv = list->lv_last->li_tv; | 3148 *rettv = list->lv_last->li_tv; |
3144 list->lv_last->li_tv.v_type = VAR_NUMBER; | 3149 list->lv_last->li_tv.v_type = VAR_NUMBER; |
3145 free_tv(listtv); | 3150 free_tv(listtv); |
3146 } | 3151 } |
3147 } | 3152 } |
3153 free_job_options(&opt); | |
3148 } | 3154 } |
3149 | 3155 |
3150 /* | 3156 /* |
3151 * common for "ch_evalraw()" and "ch_sendraw()" | 3157 * common for "ch_evalraw()" and "ch_sendraw()" |
3152 */ | 3158 */ |
3173 timeout = opt.jo_timeout; | 3179 timeout = opt.jo_timeout; |
3174 else | 3180 else |
3175 timeout = channel_get_timeout(channel, part_read); | 3181 timeout = channel_get_timeout(channel, part_read); |
3176 rettv->vval.v_string = channel_read_block(channel, part_read, timeout); | 3182 rettv->vval.v_string = channel_read_block(channel, part_read, timeout); |
3177 } | 3183 } |
3184 free_job_options(&opt); | |
3178 } | 3185 } |
3179 | 3186 |
3180 # if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO) | 3187 # if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO) |
3181 /* | 3188 /* |
3182 * Add open channels to the poll struct. | 3189 * Add open channels to the poll struct. |
3543 return FAIL; | 3550 return FAIL; |
3544 } | 3551 } |
3545 return OK; | 3552 return OK; |
3546 } | 3553 } |
3547 | 3554 |
3555 /* | |
3556 * Clear a jobopt_T before using it. | |
3557 */ | |
3548 void | 3558 void |
3549 clear_job_options(jobopt_T *opt) | 3559 clear_job_options(jobopt_T *opt) |
3550 { | 3560 { |
3551 vim_memset(opt, 0, sizeof(jobopt_T)); | 3561 vim_memset(opt, 0, sizeof(jobopt_T)); |
3562 } | |
3563 | |
3564 /* | |
3565 * Free any members of a jobopt_T. | |
3566 */ | |
3567 void | |
3568 free_job_options(jobopt_T *opt) | |
3569 { | |
3570 if (opt->jo_partial != NULL) | |
3571 partial_unref(opt->jo_partial); | |
3572 if (opt->jo_out_partial != NULL) | |
3573 partial_unref(opt->jo_out_partial); | |
3574 if (opt->jo_err_partial != NULL) | |
3575 partial_unref(opt->jo_err_partial); | |
3576 if (opt->jo_close_partial != NULL) | |
3577 partial_unref(opt->jo_close_partial); | |
3552 } | 3578 } |
3553 | 3579 |
3554 /* | 3580 /* |
3555 * Get the PART_ number from the first character of an option name. | 3581 * Get the PART_ number from the first character of an option name. |
3556 */ | 3582 */ |
4051 job = job_alloc(); | 4077 job = job_alloc(); |
4052 if (job == NULL) | 4078 if (job == NULL) |
4053 return NULL; | 4079 return NULL; |
4054 | 4080 |
4055 job->jv_status = JOB_FAILED; | 4081 job->jv_status = JOB_FAILED; |
4082 #ifndef USE_ARGV | |
4083 ga_init2(&ga, (int)sizeof(char*), 20); | |
4084 #endif | |
4056 | 4085 |
4057 /* Default mode is NL. */ | 4086 /* Default mode is NL. */ |
4058 clear_job_options(&opt); | 4087 clear_job_options(&opt); |
4059 opt.jo_mode = MODE_NL; | 4088 opt.jo_mode = MODE_NL; |
4060 if (get_job_options(&argvars[1], &opt, | 4089 if (get_job_options(&argvars[1], &opt, |
4061 JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL + JO_STOPONEXIT | 4090 JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL + JO_STOPONEXIT |
4062 + JO_EXIT_CB + JO_OUT_IO + JO_BLOCK_WRITE) == FAIL) | 4091 + JO_EXIT_CB + JO_OUT_IO + JO_BLOCK_WRITE) == FAIL) |
4063 return job; | 4092 goto theend; |
4064 | 4093 |
4065 /* Check that when io is "file" that there is a file name. */ | 4094 /* Check that when io is "file" that there is a file name. */ |
4066 for (part = PART_OUT; part <= PART_IN; ++part) | 4095 for (part = PART_OUT; part <= PART_IN; ++part) |
4067 if ((opt.jo_set & (JO_OUT_IO << (part - PART_OUT))) | 4096 if ((opt.jo_set & (JO_OUT_IO << (part - PART_OUT))) |
4068 && opt.jo_io[part] == JIO_FILE | 4097 && opt.jo_io[part] == JIO_FILE |
4069 && (!(opt.jo_set & (JO_OUT_NAME << (part - PART_OUT))) | 4098 && (!(opt.jo_set & (JO_OUT_NAME << (part - PART_OUT))) |
4070 || *opt.jo_io_name[part] == NUL)) | 4099 || *opt.jo_io_name[part] == NUL)) |
4071 { | 4100 { |
4072 EMSG(_("E920: _io file requires _name to be set")); | 4101 EMSG(_("E920: _io file requires _name to be set")); |
4073 return job; | 4102 goto theend; |
4074 } | 4103 } |
4075 | 4104 |
4076 if ((opt.jo_set & JO_IN_IO) && opt.jo_io[PART_IN] == JIO_BUFFER) | 4105 if ((opt.jo_set & JO_IN_IO) && opt.jo_io[PART_IN] == JIO_BUFFER) |
4077 { | 4106 { |
4078 buf_T *buf = NULL; | 4107 buf_T *buf = NULL; |
4089 EMSG(_("E915: in_io buffer requires in_buf or in_name to be set")); | 4118 EMSG(_("E915: in_io buffer requires in_buf or in_name to be set")); |
4090 } | 4119 } |
4091 else | 4120 else |
4092 buf = buflist_find_by_name(opt.jo_io_name[PART_IN], FALSE); | 4121 buf = buflist_find_by_name(opt.jo_io_name[PART_IN], FALSE); |
4093 if (buf == NULL) | 4122 if (buf == NULL) |
4094 return job; | 4123 goto theend; |
4095 if (buf->b_ml.ml_mfp == NULL) | 4124 if (buf->b_ml.ml_mfp == NULL) |
4096 { | 4125 { |
4097 char_u numbuf[NUMBUFLEN]; | 4126 char_u numbuf[NUMBUFLEN]; |
4098 char_u *s; | 4127 char_u *s; |
4099 | 4128 |
4103 s = numbuf; | 4132 s = numbuf; |
4104 } | 4133 } |
4105 else | 4134 else |
4106 s = opt.jo_io_name[PART_IN]; | 4135 s = opt.jo_io_name[PART_IN]; |
4107 EMSG2(_("E918: buffer must be loaded: %s"), s); | 4136 EMSG2(_("E918: buffer must be loaded: %s"), s); |
4108 return job; | 4137 goto theend; |
4109 } | 4138 } |
4110 job->jv_in_buf = buf; | 4139 job->jv_in_buf = buf; |
4111 } | 4140 } |
4112 | 4141 |
4113 job_set_options(job, &opt); | 4142 job_set_options(job, &opt); |
4114 | |
4115 #ifndef USE_ARGV | |
4116 ga_init2(&ga, (int)sizeof(char*), 20); | |
4117 #endif | |
4118 | 4143 |
4119 if (argvars[0].v_type == VAR_STRING) | 4144 if (argvars[0].v_type == VAR_STRING) |
4120 { | 4145 { |
4121 /* Command is a string. */ | 4146 /* Command is a string. */ |
4122 cmd = argvars[0].vval.v_string; | 4147 cmd = argvars[0].vval.v_string; |
4123 if (cmd == NULL || *cmd == NUL) | 4148 if (cmd == NULL || *cmd == NUL) |
4124 { | 4149 { |
4125 EMSG(_(e_invarg)); | 4150 EMSG(_(e_invarg)); |
4126 return job; | 4151 goto theend; |
4127 } | 4152 } |
4128 #ifdef USE_ARGV | 4153 #ifdef USE_ARGV |
4129 if (mch_parse_cmd(cmd, FALSE, &argv, &argc) == FAIL) | 4154 if (mch_parse_cmd(cmd, FALSE, &argv, &argc) == FAIL) |
4130 return job; | 4155 goto theend; |
4131 argv[argc] = NULL; | 4156 argv[argc] = NULL; |
4132 #endif | 4157 #endif |
4133 } | 4158 } |
4134 else if (argvars[0].v_type != VAR_LIST | 4159 else if (argvars[0].v_type != VAR_LIST |
4135 || argvars[0].vval.v_list == NULL | 4160 || argvars[0].vval.v_list == NULL |
4136 || argvars[0].vval.v_list->lv_len < 1) | 4161 || argvars[0].vval.v_list->lv_len < 1) |
4137 { | 4162 { |
4138 EMSG(_(e_invarg)); | 4163 EMSG(_(e_invarg)); |
4139 return job; | 4164 goto theend; |
4140 } | 4165 } |
4141 else | 4166 else |
4142 { | 4167 { |
4143 list_T *l = argvars[0].vval.v_list; | 4168 list_T *l = argvars[0].vval.v_list; |
4144 listitem_T *li; | 4169 listitem_T *li; |
4146 | 4171 |
4147 #ifdef USE_ARGV | 4172 #ifdef USE_ARGV |
4148 /* Pass argv[] to mch_call_shell(). */ | 4173 /* Pass argv[] to mch_call_shell(). */ |
4149 argv = (char **)alloc(sizeof(char *) * (l->lv_len + 1)); | 4174 argv = (char **)alloc(sizeof(char *) * (l->lv_len + 1)); |
4150 if (argv == NULL) | 4175 if (argv == NULL) |
4151 return job; | 4176 goto theend; |
4152 #endif | 4177 #endif |
4153 for (li = l->lv_first; li != NULL; li = li->li_next) | 4178 for (li = l->lv_first; li != NULL; li = li->li_next) |
4154 { | 4179 { |
4155 s = get_tv_string_chk(&li->li_tv); | 4180 s = get_tv_string_chk(&li->li_tv); |
4156 if (s == NULL) | 4181 if (s == NULL) |
4220 #ifdef USE_ARGV | 4245 #ifdef USE_ARGV |
4221 vim_free(argv); | 4246 vim_free(argv); |
4222 #else | 4247 #else |
4223 vim_free(ga.ga_data); | 4248 vim_free(ga.ga_data); |
4224 #endif | 4249 #endif |
4250 free_job_options(&opt); | |
4225 return job; | 4251 return job; |
4226 } | 4252 } |
4227 | 4253 |
4228 /* | 4254 /* |
4229 * Get the status of "job" and invoke the exit callback when needed. | 4255 * Get the status of "job" and invoke the exit callback when needed. |