Mercurial > vim
comparison src/channel.c @ 8761:f8707ec9efe4 v7.4.1669
commit https://github.com/vim/vim/commit/8b877ac38e96424a08a8b8eb713ef4b3cf0064be
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Mar 28 19:16:20 2016 +0200
patch 7.4.1669
Problem: When writing buffer lines to a pipe Vim may block.
Solution: Avoid blocking, write more lines later.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Mon, 28 Mar 2016 19:30:05 +0200 |
parents | cc2ef7367643 |
children | 23b7f05a7f48 |
comparison
equal
deleted
inserted
replaced
8760:e43830c12eb2 | 8761:f8707ec9efe4 |
---|---|
971 if (options->jo_in_top == 0 && !(options->jo_set & JO_IN_BOT)) | 971 if (options->jo_in_top == 0 && !(options->jo_set & JO_IN_BOT)) |
972 { | 972 { |
973 /* Special mode: send last-but-one line when appending a line | 973 /* Special mode: send last-but-one line when appending a line |
974 * to the buffer. */ | 974 * to the buffer. */ |
975 in_part->ch_buffer->b_write_to_channel = TRUE; | 975 in_part->ch_buffer->b_write_to_channel = TRUE; |
976 in_part->ch_buf_append = TRUE; | |
976 in_part->ch_buf_top = | 977 in_part->ch_buf_top = |
977 in_part->ch_buffer->b_ml.ml_line_count + 1; | 978 in_part->ch_buffer->b_ml.ml_line_count + 1; |
978 } | 979 } |
979 else | 980 else |
980 in_part->ch_buf_top = options->jo_in_top; | 981 in_part->ch_buf_top = options->jo_in_top; |
1045 channel->ch_part[part].ch_timeout = opt->jo_timeout; | 1046 channel->ch_part[part].ch_timeout = opt->jo_timeout; |
1046 if (opt->jo_set & JO_OUT_TIMEOUT) | 1047 if (opt->jo_set & JO_OUT_TIMEOUT) |
1047 channel->ch_part[PART_OUT].ch_timeout = opt->jo_out_timeout; | 1048 channel->ch_part[PART_OUT].ch_timeout = opt->jo_out_timeout; |
1048 if (opt->jo_set & JO_ERR_TIMEOUT) | 1049 if (opt->jo_set & JO_ERR_TIMEOUT) |
1049 channel->ch_part[PART_ERR].ch_timeout = opt->jo_err_timeout; | 1050 channel->ch_part[PART_ERR].ch_timeout = opt->jo_err_timeout; |
1051 if (opt->jo_set & JO_BLOCK_WRITE) | |
1052 channel->ch_part[PART_IN].ch_block_write = 1; | |
1050 | 1053 |
1051 if (opt->jo_set & JO_CALLBACK) | 1054 if (opt->jo_set & JO_CALLBACK) |
1052 { | 1055 { |
1053 cbp = &channel->ch_callback; | 1056 cbp = &channel->ch_callback; |
1054 pp = &channel->ch_partial; | 1057 pp = &channel->ch_partial; |
1191 channel_send(channel, PART_IN, p, "write_buf_line()"); | 1194 channel_send(channel, PART_IN, p, "write_buf_line()"); |
1192 vim_free(p); | 1195 vim_free(p); |
1193 } | 1196 } |
1194 | 1197 |
1195 /* | 1198 /* |
1199 * Return TRUE if "channel" can be written to. | |
1200 * Returns FALSE if the input is closed or the write would block. | |
1201 */ | |
1202 static int | |
1203 can_write_buf_line(channel_T *channel) | |
1204 { | |
1205 chanpart_T *in_part = &channel->ch_part[PART_IN]; | |
1206 | |
1207 if (in_part->ch_fd == INVALID_FD) | |
1208 return FALSE; /* pipe was closed */ | |
1209 | |
1210 /* for testing: block every other attempt to write */ | |
1211 if (in_part->ch_block_write == 1) | |
1212 in_part->ch_block_write = -1; | |
1213 else if (in_part->ch_block_write == -1) | |
1214 in_part->ch_block_write = 1; | |
1215 | |
1216 /* TODO: Win32 implementation, probably using WaitForMultipleObjects() */ | |
1217 #ifndef WIN32 | |
1218 { | |
1219 # if defined(HAVE_SELECT) | |
1220 struct timeval tval; | |
1221 fd_set wfds; | |
1222 int ret; | |
1223 | |
1224 FD_ZERO(&wfds); | |
1225 FD_SET((int)in_part->ch_fd, &wfds); | |
1226 tval.tv_sec = 0; | |
1227 tval.tv_usec = 0; | |
1228 for (;;) | |
1229 { | |
1230 ret = select((int)in_part->ch_fd + 1, NULL, &wfds, NULL, &tval); | |
1231 # ifdef EINTR | |
1232 SOCK_ERRNO; | |
1233 if (ret == -1 && errno == EINTR) | |
1234 continue; | |
1235 # endif | |
1236 if (ret <= 0 || in_part->ch_block_write == 1) | |
1237 { | |
1238 if (ret > 0) | |
1239 ch_log(channel, "FAKED Input not ready for writing"); | |
1240 else | |
1241 ch_log(channel, "Input not ready for writing"); | |
1242 return FALSE; | |
1243 } | |
1244 break; | |
1245 } | |
1246 # else | |
1247 struct pollfd fds; | |
1248 | |
1249 fds.fd = in_part->ch_fd; | |
1250 fds.events = POLLOUT; | |
1251 if (poll(&fds, 1, 0) <= 0) | |
1252 { | |
1253 ch_log(channel, "Input not ready for writing"); | |
1254 return FALSE; | |
1255 } | |
1256 if (in_part->ch_block_write == 1) | |
1257 { | |
1258 ch_log(channel, "FAKED Input not ready for writing"); | |
1259 return FALSE; | |
1260 } | |
1261 # endif | |
1262 } | |
1263 #endif | |
1264 return TRUE; | |
1265 } | |
1266 | |
1267 /* | |
1196 * Write any lines to the input channel. | 1268 * Write any lines to the input channel. |
1197 */ | 1269 */ |
1198 void | 1270 static void |
1199 channel_write_in(channel_T *channel) | 1271 channel_write_in(channel_T *channel) |
1200 { | 1272 { |
1201 chanpart_T *in_part = &channel->ch_part[PART_IN]; | 1273 chanpart_T *in_part = &channel->ch_part[PART_IN]; |
1202 linenr_T lnum; | 1274 linenr_T lnum; |
1203 buf_T *buf = in_part->ch_buffer; | 1275 buf_T *buf = in_part->ch_buffer; |
1204 int written = 0; | 1276 int written = 0; |
1205 | 1277 |
1206 if (buf == NULL) | 1278 if (buf == NULL || in_part->ch_buf_append) |
1207 return; | 1279 return; /* no buffer or using appending */ |
1208 if (!buf_valid(buf) || buf->b_ml.ml_mfp == NULL) | 1280 if (!buf_valid(buf) || buf->b_ml.ml_mfp == NULL) |
1209 { | 1281 { |
1210 /* buffer was wiped out or unloaded */ | 1282 /* buffer was wiped out or unloaded */ |
1211 in_part->ch_buffer = NULL; | 1283 in_part->ch_buffer = NULL; |
1212 return; | 1284 return; |
1213 } | 1285 } |
1214 | 1286 |
1215 for (lnum = in_part->ch_buf_top; lnum <= in_part->ch_buf_bot | 1287 for (lnum = in_part->ch_buf_top; lnum <= in_part->ch_buf_bot |
1216 && lnum <= buf->b_ml.ml_line_count; ++lnum) | 1288 && lnum <= buf->b_ml.ml_line_count; ++lnum) |
1217 { | 1289 { |
1218 if (in_part->ch_fd == INVALID_FD) | 1290 if (!can_write_buf_line(channel)) |
1219 /* pipe was closed */ | 1291 break; |
1220 return; | |
1221 /* TODO: check if channel can be written to, do not block on write */ | |
1222 write_buf_line(buf, lnum, channel); | 1292 write_buf_line(buf, lnum, channel); |
1223 ++written; | 1293 ++written; |
1224 } | 1294 } |
1225 | 1295 |
1226 if (written == 1) | 1296 if (written == 1) |
1227 ch_logn(channel, "written line %d to channel", (int)lnum - 1); | 1297 ch_logn(channel, "written line %d to channel", (int)lnum - 1); |
1228 else if (written > 1) | 1298 else if (written > 1) |
1229 ch_logn(channel, "written %d lines to channel", written); | 1299 ch_logn(channel, "written %d lines to channel", written); |
1230 | 1300 |
1231 in_part->ch_buf_top = lnum; | 1301 in_part->ch_buf_top = lnum; |
1302 if (lnum > buf->b_ml.ml_line_count) | |
1303 { | |
1304 /* Writing is done, no longer need the buffer. */ | |
1305 in_part->ch_buffer = NULL; | |
1306 ch_log(channel, "Finished writing all lines to channel"); | |
1307 } | |
1308 else | |
1309 ch_logn(channel, "Still %d more lines to write", | |
1310 buf->b_ml.ml_line_count - lnum + 1); | |
1311 } | |
1312 | |
1313 /* | |
1314 * Write any lines waiting to be written to a channel. | |
1315 */ | |
1316 void | |
1317 channel_write_any_lines() | |
1318 { | |
1319 channel_T *channel; | |
1320 | |
1321 for (channel = first_channel; channel != NULL; channel = channel->ch_next) | |
1322 { | |
1323 chanpart_T *in_part = &channel->ch_part[PART_IN]; | |
1324 | |
1325 if (in_part->ch_buffer != NULL) | |
1326 { | |
1327 if (in_part->ch_buf_append) | |
1328 channel_write_new_lines(in_part->ch_buffer); | |
1329 else | |
1330 channel_write_in(channel); | |
1331 } | |
1332 } | |
1232 } | 1333 } |
1233 | 1334 |
1234 /* | 1335 /* |
1235 * Write appended lines above the last one in "buf" to the channel. | 1336 * Write appended lines above the last one in "buf" to the channel. |
1236 */ | 1337 */ |
1246 { | 1347 { |
1247 chanpart_T *in_part = &channel->ch_part[PART_IN]; | 1348 chanpart_T *in_part = &channel->ch_part[PART_IN]; |
1248 linenr_T lnum; | 1349 linenr_T lnum; |
1249 int written = 0; | 1350 int written = 0; |
1250 | 1351 |
1251 if (in_part->ch_buffer == buf) | 1352 if (in_part->ch_buffer == buf && in_part->ch_buf_append) |
1252 { | 1353 { |
1253 if (in_part->ch_fd == INVALID_FD) | 1354 if (in_part->ch_fd == INVALID_FD) |
1254 /* pipe was closed */ | 1355 continue; /* pipe was closed */ |
1255 continue; | |
1256 found_one = TRUE; | 1356 found_one = TRUE; |
1257 for (lnum = in_part->ch_buf_bot; lnum < buf->b_ml.ml_line_count; | 1357 for (lnum = in_part->ch_buf_bot; lnum < buf->b_ml.ml_line_count; |
1258 ++lnum) | 1358 ++lnum) |
1259 { | 1359 { |
1360 if (!can_write_buf_line(channel)) | |
1361 break; | |
1260 write_buf_line(buf, lnum, channel); | 1362 write_buf_line(buf, lnum, channel); |
1261 ++written; | 1363 ++written; |
1262 } | 1364 } |
1263 | 1365 |
1264 if (written == 1) | 1366 if (written == 1) |
1265 ch_logn(channel, "written line %d to channel", (int)lnum - 1); | 1367 ch_logn(channel, "written line %d to channel", (int)lnum - 1); |
1266 else if (written > 1) | 1368 else if (written > 1) |
1267 ch_logn(channel, "written %d lines to channel", written); | 1369 ch_logn(channel, "written %d lines to channel", written); |
1370 if (lnum < buf->b_ml.ml_line_count) | |
1371 ch_logn(channel, "Still %d more lines to write", | |
1372 buf->b_ml.ml_line_count - lnum); | |
1268 | 1373 |
1269 in_part->ch_buf_bot = lnum; | 1374 in_part->ch_buf_bot = lnum; |
1270 } | 1375 } |
1271 } | 1376 } |
1272 if (!found_one) | 1377 if (!found_one) |
2377 #define DETACH_MSG_RAW "DETACH\n" | 2482 #define DETACH_MSG_RAW "DETACH\n" |
2378 | 2483 |
2379 /* Buffer size for reading incoming messages. */ | 2484 /* Buffer size for reading incoming messages. */ |
2380 #define MAXMSGSIZE 4096 | 2485 #define MAXMSGSIZE 4096 |
2381 | 2486 |
2487 #if defined(HAVE_SELECT) | |
2488 /* | |
2489 * Add write fds where we are waiting for writing to be possible. | |
2490 */ | |
2491 static int | |
2492 channel_fill_wfds(int maxfd_arg, fd_set *wfds) | |
2493 { | |
2494 int maxfd = maxfd_arg; | |
2495 channel_T *ch; | |
2496 | |
2497 for (ch = first_channel; ch != NULL; ch = ch->ch_next) | |
2498 { | |
2499 chanpart_T *in_part = &ch->ch_part[PART_IN]; | |
2500 | |
2501 if (in_part->ch_fd != INVALID_FD && in_part->ch_buffer != NULL) | |
2502 { | |
2503 FD_SET((int)in_part->ch_fd, wfds); | |
2504 if ((int)in_part->ch_fd >= maxfd) | |
2505 maxfd = (int)in_part->ch_fd + 1; | |
2506 } | |
2507 } | |
2508 return maxfd; | |
2509 } | |
2510 #else | |
2511 /* | |
2512 * Add write fds where we are waiting for writing to be possible. | |
2513 */ | |
2514 static int | |
2515 channel_fill_poll_write(int nfd_in, struct pollfd *fds) | |
2516 { | |
2517 int nfd = nfd_in; | |
2518 channel_T *ch; | |
2519 | |
2520 for (ch = first_channel; ch != NULL; ch = ch->ch_next) | |
2521 { | |
2522 chanpart_T *in_part = &ch->ch_part[PART_IN]; | |
2523 | |
2524 if (in_part->ch_fd != INVALID_FD && in_part->ch_buffer != NULL) | |
2525 { | |
2526 in_part->ch_poll_idx = nfd; | |
2527 fds[nfd].fd = in_part->ch_fd; | |
2528 fds[nfd].events = POLLOUT; | |
2529 ++nfd; | |
2530 } | |
2531 else | |
2532 in_part->ch_poll_idx = -1; | |
2533 } | |
2534 return nfd; | |
2535 } | |
2536 #endif | |
2537 | |
2382 /* | 2538 /* |
2383 * Check for reading from "fd" with "timeout" msec. | 2539 * Check for reading from "fd" with "timeout" msec. |
2384 * Return FAIL when there is nothing to read. | 2540 * Return FAIL when there is nothing to read. |
2385 */ | 2541 */ |
2386 static int | 2542 static int |
2401 while (TRUE) | 2557 while (TRUE) |
2402 { | 2558 { |
2403 if (PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL) | 2559 if (PeekNamedPipe((HANDLE)fd, NULL, 0, NULL, &nread, NULL) |
2404 && nread > 0) | 2560 && nread > 0) |
2405 return OK; | 2561 return OK; |
2562 | |
2563 /* perhaps write some buffer lines */ | |
2564 channel_write_any_lines(); | |
2565 | |
2406 sleep_time = deadline - GetTickCount(); | 2566 sleep_time = deadline - GetTickCount(); |
2407 if (sleep_time <= 0) | 2567 if (sleep_time <= 0) |
2408 break; | 2568 break; |
2409 /* Wait for a little while. Very short at first, up to 10 msec | 2569 /* Wait for a little while. Very short at first, up to 10 msec |
2410 * after looping a few times. */ | 2570 * after looping a few times. */ |
2420 #endif | 2580 #endif |
2421 { | 2581 { |
2422 #if defined(HAVE_SELECT) | 2582 #if defined(HAVE_SELECT) |
2423 struct timeval tval; | 2583 struct timeval tval; |
2424 fd_set rfds; | 2584 fd_set rfds; |
2425 int ret; | 2585 fd_set wfds; |
2426 | 2586 int ret; |
2427 FD_ZERO(&rfds); | 2587 int maxfd; |
2428 FD_SET((int)fd, &rfds); | 2588 |
2429 tval.tv_sec = timeout / 1000; | 2589 tval.tv_sec = timeout / 1000; |
2430 tval.tv_usec = (timeout % 1000) * 1000; | 2590 tval.tv_usec = (timeout % 1000) * 1000; |
2431 for (;;) | 2591 for (;;) |
2432 { | 2592 { |
2433 ret = select((int)fd + 1, &rfds, NULL, NULL, &tval); | 2593 FD_ZERO(&rfds); |
2594 FD_SET((int)fd, &rfds); | |
2595 | |
2596 /* Write lines to a pipe when a pipe can be written to. Need to | |
2597 * set this every time, some buffers may be done. */ | |
2598 maxfd = (int)fd + 1; | |
2599 FD_ZERO(&wfds); | |
2600 maxfd = channel_fill_wfds(maxfd, &wfds); | |
2601 | |
2602 ret = select(maxfd, &rfds, &wfds, NULL, &tval); | |
2434 # ifdef EINTR | 2603 # ifdef EINTR |
2435 SOCK_ERRNO; | 2604 SOCK_ERRNO; |
2436 if (ret == -1 && errno == EINTR) | 2605 if (ret == -1 && errno == EINTR) |
2437 continue; | 2606 continue; |
2438 # endif | 2607 # endif |
2439 if (ret > 0) | 2608 if (ret > 0) |
2440 return OK; | 2609 { |
2610 if (FD_ISSET(fd, &rfds)) | |
2611 return OK; | |
2612 channel_write_any_lines(); | |
2613 continue; | |
2614 } | |
2441 break; | 2615 break; |
2442 } | 2616 } |
2443 #else | 2617 #else |
2444 struct pollfd fds; | 2618 for (;;) |
2445 | 2619 { |
2446 fds.fd = fd; | 2620 struct pollfd fds[MAX_OPEN_CHANNELS + 1]; |
2447 fds.events = POLLIN; | 2621 int nfd = 1; |
2448 if (poll(&fds, 1, timeout) > 0) | 2622 |
2449 return OK; | 2623 fds[0].fd = fd; |
2624 fds[0].events = POLLIN; | |
2625 nfd = channel_fill_poll_write(nfd, fds); | |
2626 if (poll(fds, nfd, timeout) > 0) | |
2627 { | |
2628 if (fds[0].revents & POLLIN) | |
2629 return OK; | |
2630 channel_write_any_lines(); | |
2631 continue; | |
2632 } | |
2633 break; | |
2634 } | |
2450 #endif | 2635 #endif |
2451 } | 2636 } |
2452 return FAIL; | 2637 return FAIL; |
2453 } | 2638 } |
2454 | 2639 |
3008 | 3193 |
3009 for (channel = first_channel; channel != NULL; channel = channel->ch_next) | 3194 for (channel = first_channel; channel != NULL; channel = channel->ch_next) |
3010 { | 3195 { |
3011 for (part = PART_SOCK; part < PART_IN; ++part) | 3196 for (part = PART_SOCK; part < PART_IN; ++part) |
3012 { | 3197 { |
3013 if (channel->ch_part[part].ch_fd != INVALID_FD) | 3198 chanpart_T *ch_part = &channel->ch_part[part]; |
3014 { | 3199 |
3015 channel->ch_part[part].ch_poll_idx = nfd; | 3200 if (ch_part->ch_fd != INVALID_FD) |
3016 fds[nfd].fd = channel->ch_part[part].ch_fd; | 3201 { |
3202 ch_part->ch_poll_idx = nfd; | |
3203 fds[nfd].fd = ch_part->ch_fd; | |
3017 fds[nfd].events = POLLIN; | 3204 fds[nfd].events = POLLIN; |
3018 nfd++; | 3205 nfd++; |
3019 } | 3206 } |
3020 else | 3207 else |
3021 channel->ch_part[part].ch_poll_idx = -1; | 3208 channel->ch_part[part].ch_poll_idx = -1; |
3022 } | 3209 } |
3023 } | 3210 } |
3211 | |
3212 nfd = channel_fill_poll_write(nfd, fds); | |
3024 | 3213 |
3025 return nfd; | 3214 return nfd; |
3026 } | 3215 } |
3027 | 3216 |
3028 /* | 3217 /* |
3033 { | 3222 { |
3034 int ret = ret_in; | 3223 int ret = ret_in; |
3035 channel_T *channel; | 3224 channel_T *channel; |
3036 struct pollfd *fds = fds_in; | 3225 struct pollfd *fds = fds_in; |
3037 int part; | 3226 int part; |
3227 int idx; | |
3228 chanpart_T *in_part; | |
3038 | 3229 |
3039 for (channel = first_channel; channel != NULL; channel = channel->ch_next) | 3230 for (channel = first_channel; channel != NULL; channel = channel->ch_next) |
3040 { | 3231 { |
3041 for (part = PART_SOCK; part < PART_IN; ++part) | 3232 for (part = PART_SOCK; part < PART_IN; ++part) |
3042 { | 3233 { |
3043 int idx = channel->ch_part[part].ch_poll_idx; | 3234 idx = channel->ch_part[part].ch_poll_idx; |
3044 | 3235 |
3045 if (ret > 0 && idx != -1 && fds[idx].revents & POLLIN) | 3236 if (ret > 0 && idx != -1 && (fds[idx].revents & POLLIN)) |
3046 { | 3237 { |
3047 channel_read(channel, part, "channel_poll_check"); | 3238 channel_read(channel, part, "channel_poll_check"); |
3048 --ret; | 3239 --ret; |
3049 } | 3240 } |
3050 } | 3241 } |
3242 | |
3243 in_part = &channel->ch_part[PART_IN]; | |
3244 idx = in_part->ch_poll_idx; | |
3245 if (ret > 0 && idx != -1 && (fds[idx].revents & POLLOUT)) | |
3246 { | |
3247 if (in_part->ch_buf_append) | |
3248 { | |
3249 if (in_part->ch_buffer != NULL) | |
3250 channel_write_new_lines(in_part->ch_buffer); | |
3251 } | |
3252 else | |
3253 channel_write_in(channel); | |
3254 --ret; | |
3255 } | |
3051 } | 3256 } |
3052 | 3257 |
3053 return ret; | 3258 return ret; |
3054 } | 3259 } |
3055 # endif /* UNIX && !HAVE_SELECT */ | 3260 # endif /* UNIX && !HAVE_SELECT */ |
3056 | 3261 |
3057 # if (!defined(WIN32) && defined(HAVE_SELECT)) || defined(PROTO) | 3262 # if (!defined(WIN32) && defined(HAVE_SELECT)) || defined(PROTO) |
3058 /* | 3263 /* |
3059 * The type of "rfds" is hidden to avoid problems with the function proto. | 3264 * The "fd_set" type is hidden to avoid problems with the function proto. |
3060 */ | 3265 */ |
3061 int | 3266 int |
3062 channel_select_setup(int maxfd_in, void *rfds_in) | 3267 channel_select_setup(int maxfd_in, void *rfds_in, void *wfds_in) |
3063 { | 3268 { |
3064 int maxfd = maxfd_in; | 3269 int maxfd = maxfd_in; |
3065 channel_T *channel; | 3270 channel_T *channel; |
3066 fd_set *rfds = rfds_in; | 3271 fd_set *rfds = rfds_in; |
3272 fd_set *wfds = wfds_in; | |
3067 int part; | 3273 int part; |
3068 | 3274 |
3069 for (channel = first_channel; channel != NULL; channel = channel->ch_next) | 3275 for (channel = first_channel; channel != NULL; channel = channel->ch_next) |
3070 { | 3276 { |
3071 for (part = PART_SOCK; part < PART_IN; ++part) | 3277 for (part = PART_SOCK; part < PART_IN; ++part) |
3079 maxfd = (int)fd; | 3285 maxfd = (int)fd; |
3080 } | 3286 } |
3081 } | 3287 } |
3082 } | 3288 } |
3083 | 3289 |
3290 maxfd = channel_fill_wfds(maxfd, wfds); | |
3291 | |
3084 return maxfd; | 3292 return maxfd; |
3085 } | 3293 } |
3086 | 3294 |
3087 /* | 3295 /* |
3088 * The type of "rfds" is hidden to avoid problems with the function proto. | 3296 * The "fd_set" type is hidden to avoid problems with the function proto. |
3089 */ | 3297 */ |
3090 int | 3298 int |
3091 channel_select_check(int ret_in, void *rfds_in) | 3299 channel_select_check(int ret_in, void *rfds_in, void *wfds_in) |
3092 { | 3300 { |
3093 int ret = ret_in; | 3301 int ret = ret_in; |
3094 channel_T *channel; | 3302 channel_T *channel; |
3095 fd_set *rfds = rfds_in; | 3303 fd_set *rfds = rfds_in; |
3304 fd_set *wfds = wfds_in; | |
3096 int part; | 3305 int part; |
3306 chanpart_T *in_part; | |
3097 | 3307 |
3098 for (channel = first_channel; channel != NULL; channel = channel->ch_next) | 3308 for (channel = first_channel; channel != NULL; channel = channel->ch_next) |
3099 { | 3309 { |
3100 for (part = PART_SOCK; part < PART_IN; ++part) | 3310 for (part = PART_SOCK; part < PART_IN; ++part) |
3101 { | 3311 { |
3104 if (ret > 0 && fd != INVALID_FD && FD_ISSET(fd, rfds)) | 3314 if (ret > 0 && fd != INVALID_FD && FD_ISSET(fd, rfds)) |
3105 { | 3315 { |
3106 channel_read(channel, part, "channel_select_check"); | 3316 channel_read(channel, part, "channel_select_check"); |
3107 --ret; | 3317 --ret; |
3108 } | 3318 } |
3319 } | |
3320 | |
3321 in_part = &channel->ch_part[PART_IN]; | |
3322 if (ret > 0 && in_part->ch_fd != INVALID_FD | |
3323 && FD_ISSET(in_part->ch_fd, wfds)) | |
3324 { | |
3325 if (in_part->ch_buf_append) | |
3326 { | |
3327 if (in_part->ch_buffer != NULL) | |
3328 channel_write_new_lines(in_part->ch_buffer); | |
3329 } | |
3330 else | |
3331 channel_write_in(channel); | |
3332 --ret; | |
3109 } | 3333 } |
3110 } | 3334 } |
3111 | 3335 |
3112 return ret; | 3336 return ret; |
3113 } | 3337 } |
3606 { | 3830 { |
3607 EMSG2(_(e_invarg2), "exit_cb"); | 3831 EMSG2(_(e_invarg2), "exit_cb"); |
3608 return FAIL; | 3832 return FAIL; |
3609 } | 3833 } |
3610 } | 3834 } |
3835 else if (STRCMP(hi->hi_key, "block_write") == 0) | |
3836 { | |
3837 if (!(supported & JO_BLOCK_WRITE)) | |
3838 break; | |
3839 opt->jo_set |= JO_BLOCK_WRITE; | |
3840 opt->jo_block_write = get_tv_number(item); | |
3841 } | |
3611 else | 3842 else |
3612 break; | 3843 break; |
3613 --todo; | 3844 --todo; |
3614 } | 3845 } |
3615 if (todo > 0) | 3846 if (todo > 0) |
3825 | 4056 |
3826 /* Default mode is NL. */ | 4057 /* Default mode is NL. */ |
3827 clear_job_options(&opt); | 4058 clear_job_options(&opt); |
3828 opt.jo_mode = MODE_NL; | 4059 opt.jo_mode = MODE_NL; |
3829 if (get_job_options(&argvars[1], &opt, | 4060 if (get_job_options(&argvars[1], &opt, |
3830 JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL | 4061 JO_MODE_ALL + JO_CB_ALL + JO_TIMEOUT_ALL + JO_STOPONEXIT |
3831 + JO_STOPONEXIT + JO_EXIT_CB + JO_OUT_IO) == FAIL) | 4062 + JO_EXIT_CB + JO_OUT_IO + JO_BLOCK_WRITE) == FAIL) |
3832 return job; | 4063 return job; |
3833 | 4064 |
3834 /* Check that when io is "file" that there is a file name. */ | 4065 /* Check that when io is "file" that there is a file name. */ |
3835 for (part = PART_OUT; part <= PART_IN; ++part) | 4066 for (part = PART_OUT; part <= PART_IN; ++part) |
3836 if ((opt.jo_set & (JO_OUT_IO << (part - PART_OUT))) | 4067 if ((opt.jo_set & (JO_OUT_IO << (part - PART_OUT))) |