aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTroels Nielsen2012-06-17 17:00:37 +0800
committerChong Yidong2012-06-17 17:00:37 +0800
commit20ca2e9451e7dbae9b24bf759c4374a674c9270a (patch)
tree869520c949ccfcf28c3d480de8007937363c816c /src
parent48d1354eb8e8e7dc759400a2f001d02587f15be2 (diff)
downloademacs-20ca2e9451e7dbae9b24bf759c4374a674c9270a.tar.gz
emacs-20ca2e9451e7dbae9b24bf759c4374a674c9270a.zip
Ensure correct ordering of process writes.
* process.c (make_process): Initialize write_queue. (write_queue_push, write_queue_pop): New functions. (send_process): Use them to maintain correct ordering of process writes. Fixes: debbugs:10815
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog7
-rw-r--r--src/process.c134
-rw-r--r--src/process.h2
3 files changed, 113 insertions, 30 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 84be53f43d6..ba029611cdb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
12012-06-17 Troels Nielsen <bn.troels@gmail.com>
2
3 * process.c (make_process): Initialize write_queue.
4 (write_queue_push, write_queue_pop): New functions.
5 (send_process): Use them to maintain correct ordering of process
6 writes (Bug#10815).
7
12012-06-17 Paul Eggert <eggert@cs.ucla.edu> 82012-06-17 Paul Eggert <eggert@cs.ucla.edu>
2 9
3 * lisp.h (eassert): Assume C89 or later. 10 * lisp.h (eassert): Assume C89 or later.
diff --git a/src/process.c b/src/process.c
index 6e454db6b4c..0434caf7574 100644
--- a/src/process.c
+++ b/src/process.c
@@ -638,6 +638,7 @@ make_process (Lisp_Object name)
638 p->status = Qrun; 638 p->status = Qrun;
639 p->mark = Fmake_marker (); 639 p->mark = Fmake_marker ();
640 p->kill_without_query = 0; 640 p->kill_without_query = 0;
641 p->write_queue = Qnil;
641 642
642#ifdef ADAPTIVE_READ_BUFFERING 643#ifdef ADAPTIVE_READ_BUFFERING
643 p->adaptive_read_buffering = 0; 644 p->adaptive_read_buffering = 0;
@@ -5371,6 +5372,78 @@ send_process_trap (int ignore)
5371 longjmp (send_process_frame, 1); 5372 longjmp (send_process_frame, 1);
5372} 5373}
5373 5374
5375/* In send_process, when a write fails temporarily,
5376 wait_reading_process_output is called. It may execute user code,
5377 e.g. timers, that attempts to write new data to the same process.
5378 We must ensure that data is sent in the right order, and not
5379 interspersed half-completed with other writes (Bug#10815). This is
5380 handled by the write_queue element of struct process. It is a list
5381 with each entry having the form
5382
5383 (string . (offset . length))
5384
5385 where STRING is a lisp string, OFFSET is the offset into the
5386 string's byte sequence from which we should begin to send, and
5387 LENGTH is the number of bytes left to send. */
5388
5389/* Create a new entry in write_queue.
5390 INPUT_OBJ should be a buffer, string Qt, or Qnil.
5391 BUF is a pointer to the string sequence of the input_obj or a C
5392 string in case of Qt or Qnil. */
5393
5394static void
5395write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj,
5396 const char *buf, int len, int front)
5397{
5398 EMACS_INT offset;
5399 Lisp_Object entry, obj;
5400
5401 if (STRINGP (input_obj))
5402 {
5403 offset = buf - SSDATA (input_obj);
5404 obj = input_obj;
5405 }
5406 else
5407 {
5408 offset = 0;
5409 obj = make_unibyte_string (buf, len);
5410 }
5411
5412 entry = Fcons (obj, Fcons (make_number (offset), make_number (len)));
5413
5414 if (front)
5415 p->write_queue = Fcons (entry, p->write_queue);
5416 else
5417 p->write_queue = nconc2 (p->write_queue, Fcons (entry, Qnil));
5418}
5419
5420/* Remove the first element in the write_queue of process P, put its
5421 contents in OBJ, BUF and LEN, and return non-zero. If the
5422 write_queue is empty, return zero. */
5423
5424static int
5425write_queue_pop (struct Lisp_Process *p, Lisp_Object *obj,
5426 const char **buf, EMACS_INT *len)
5427{
5428 Lisp_Object entry, offset_length;
5429 EMACS_INT offset;
5430
5431 if (NILP (p->write_queue))
5432 return 0;
5433
5434 entry = XCAR (p->write_queue);
5435 p->write_queue = XCDR (p->write_queue);
5436
5437 *obj = XCAR (entry);
5438 offset_length = XCDR (entry);
5439
5440 *len = XINT (XCDR (offset_length));
5441 offset = XINT (XCAR (offset_length));
5442 *buf = SDATA (*obj) + offset;
5443
5444 return 1;
5445}
5446
5374/* Send some data to process PROC. 5447/* Send some data to process PROC.
5375 BUF is the beginning of the data; LEN is the number of characters. 5448 BUF is the beginning of the data; LEN is the number of characters.
5376 OBJECT is the Lisp object that the data comes from. If OBJECT is 5449 OBJECT is the Lisp object that the data comes from. If OBJECT is
@@ -5389,11 +5462,8 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
5389 struct Lisp_Process *p = XPROCESS (proc); 5462 struct Lisp_Process *p = XPROCESS (proc);
5390 ssize_t rv; 5463 ssize_t rv;
5391 struct coding_system *coding; 5464 struct coding_system *coding;
5392 struct gcpro gcpro1;
5393 void (*volatile old_sigpipe) (int); 5465 void (*volatile old_sigpipe) (int);
5394 5466
5395 GCPRO1 (object);
5396
5397 if (p->raw_status_new) 5467 if (p->raw_status_new)
5398 update_status (p); 5468 update_status (p);
5399 if (! EQ (p->status, Qrun)) 5469 if (! EQ (p->status, Qrun))
@@ -5505,22 +5575,37 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
5505 if (!setjmp (send_process_frame)) 5575 if (!setjmp (send_process_frame))
5506 { 5576 {
5507 p = XPROCESS (proc); /* Repair any setjmp clobbering. */ 5577 p = XPROCESS (proc); /* Repair any setjmp clobbering. */
5508
5509 process_sent_to = proc; 5578 process_sent_to = proc;
5510 while (len > 0) 5579
5580 /* If there is already data in the write_queue, put the new data
5581 in the back of queue. Otherwise, ignore it. */
5582 if (!NILP (p->write_queue))
5583 write_queue_push (p, object, buf, len, 0);
5584
5585 do /* while !NILP (p->write_queue) */
5511 { 5586 {
5512 ptrdiff_t this = len; 5587 EMACS_INT cur_len = -1;
5588 const char *cur_buf;
5589 Lisp_Object cur_object;
5590
5591 /* If write_queue is empty, ignore it. */
5592 if (!write_queue_pop (p, &cur_object, &cur_buf, &cur_len))
5593 {
5594 cur_len = len;
5595 cur_buf = buf;
5596 cur_object = object;
5597 }
5513 5598
5514 /* Send this batch, using one or more write calls. */ 5599 while (cur_len > 0)
5515 while (this > 0)
5516 { 5600 {
5601 /* Send this batch, using one or more write calls. */
5517 ptrdiff_t written = 0; 5602 ptrdiff_t written = 0;
5518 int outfd = p->outfd; 5603 int outfd = p->outfd;
5519 old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap); 5604 old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap);
5520#ifdef DATAGRAM_SOCKETS 5605#ifdef DATAGRAM_SOCKETS
5521 if (DATAGRAM_CHAN_P (outfd)) 5606 if (DATAGRAM_CHAN_P (outfd))
5522 { 5607 {
5523 rv = sendto (outfd, buf, this, 5608 rv = sendto (outfd, cur_buf, cur_len,
5524 0, datagram_address[outfd].sa, 5609 0, datagram_address[outfd].sa,
5525 datagram_address[outfd].len); 5610 datagram_address[outfd].len);
5526 if (0 <= rv) 5611 if (0 <= rv)
@@ -5537,10 +5622,10 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
5537 { 5622 {
5538#ifdef HAVE_GNUTLS 5623#ifdef HAVE_GNUTLS
5539 if (p->gnutls_p) 5624 if (p->gnutls_p)
5540 written = emacs_gnutls_write (p, buf, this); 5625 written = emacs_gnutls_write (p, cur_buf, cur_len);
5541 else 5626 else
5542#endif 5627#endif
5543 written = emacs_write (outfd, buf, this); 5628 written = emacs_write (outfd, cur_buf, cur_len);
5544 rv = (written ? 0 : -1); 5629 rv = (written ? 0 : -1);
5545#ifdef ADAPTIVE_READ_BUFFERING 5630#ifdef ADAPTIVE_READ_BUFFERING
5546 if (p->read_output_delay > 0 5631 if (p->read_output_delay > 0
@@ -5595,35 +5680,26 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
5595 } 5680 }
5596#endif /* BROKEN_PTY_READ_AFTER_EAGAIN */ 5681#endif /* BROKEN_PTY_READ_AFTER_EAGAIN */
5597 5682
5598 /* Running filters might relocate buffers or strings. 5683 /* Put what we should have written in
5599 Arrange to relocate BUF. */ 5684 wait_queue */
5600 if (BUFFERP (object)) 5685 write_queue_push (p, cur_object, cur_buf, cur_len, 1);
5601 offset = BUF_PTR_BYTE_POS (XBUFFER (object),
5602 (unsigned char *) buf);
5603 else if (STRINGP (object))
5604 offset = buf - SSDATA (object);
5605
5606#ifdef EMACS_HAS_USECS 5686#ifdef EMACS_HAS_USECS
5607 wait_reading_process_output (0, 20000, 0, 0, Qnil, NULL, 0); 5687 wait_reading_process_output (0, 20000, 0, 0, Qnil, NULL, 0);
5608#else 5688#else
5609 wait_reading_process_output (1, 0, 0, 0, Qnil, NULL, 0); 5689 wait_reading_process_output (1, 0, 0, 0, Qnil, NULL, 0);
5610#endif 5690#endif
5611 5691 /* reread queue, to see what is left */
5612 if (BUFFERP (object)) 5692 break;
5613 buf = (char *) BUF_BYTE_ADDRESS (XBUFFER (object),
5614 offset);
5615 else if (STRINGP (object))
5616 buf = offset + SSDATA (object);
5617 } 5693 }
5618 else 5694 else
5619 /* This is a real error. */ 5695 /* This is a real error. */
5620 report_file_error ("writing to process", Fcons (proc, Qnil)); 5696 report_file_error ("writing to process", Fcons (proc, Qnil));
5621 } 5697 }
5622 buf += written; 5698 cur_buf += written;
5623 len -= written; 5699 cur_len -= written;
5624 this -= written;
5625 } 5700 }
5626 } 5701 }
5702 while (!NILP (p->write_queue));
5627 } 5703 }
5628 else 5704 else
5629 { 5705 {
@@ -5636,8 +5712,6 @@ send_process (volatile Lisp_Object proc, const char *volatile buf,
5636 deactivate_process (proc); 5712 deactivate_process (proc);
5637 error ("SIGPIPE raised on process %s; closed it", SDATA (p->name)); 5713 error ("SIGPIPE raised on process %s; closed it", SDATA (p->name));
5638 } 5714 }
5639
5640 UNGCPRO;
5641} 5715}
5642 5716
5643DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region, 5717DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
diff --git a/src/process.h b/src/process.h
index edb937893b0..ae4b6b61c94 100644
--- a/src/process.h
+++ b/src/process.h
@@ -77,6 +77,8 @@ struct Lisp_Process
77 Lisp_Object encode_coding_system; 77 Lisp_Object encode_coding_system;
78 /* Working buffer for encoding. */ 78 /* Working buffer for encoding. */
79 Lisp_Object encoding_buf; 79 Lisp_Object encoding_buf;
80 /* Queue for storing waiting writes */
81 Lisp_Object write_queue;
80 82
81#ifdef HAVE_GNUTLS 83#ifdef HAVE_GNUTLS
82 Lisp_Object gnutls_cred_type; 84 Lisp_Object gnutls_cred_type;