Áp dụng thời gian chờ trên tiến trình cuộc gọi / lệnh shell?


7

Trong một số trường hợp, khi ủy thác công việc cho một quy trình bên ngoài, sẽ rất hữu ích khi đặt thời gian chờ cho lệnh để ngăn Emacs treo vô thời hạn.
Thật không may, sau đây không hoạt động.

(with-timeout (1 nil)
  (call-process "/usr/bin/bash" nil t nil "-c" "sleep 10"))

Cũng vậy shell-command.

Có cách nào để đặt thời gian chờ cho các quy trình đồng bộ này không?
Đó là, tôi muốn quá trình tự động bị hủy nếu nó không kết thúc trong một số giây nhất định. Điều đó có thể không?


Tôi chưa bao giờ sử dụng with-timeout, nhưng tôi đã sử dụng kill-processdelete-process.
luật

Không chắc chắn, nhưng có thể chấp nhận đầu ra quá trình sẽ giúp. Tức là nó sẽ bảo Emacs chủ động và thực thi một số mã Elisp, được cho là đang chờ quá trình tạo ra một số đầu ra, có lẽ, đó cũng là thời điểm tốt để giết tiến trình nếu hết thời gian.
wvxvw

@wvxvw Ở call-processtrên là cài đặt đầu ra được in trên bộ đệm hiện tại (Tôi nhận được hiệu ứng tương tự nếu tôi chuyển một bộ đệm đầu ra khác). Đó có phải là ý bạn không?
Malabarba

Không, xin lỗi, tôi nhầm lẫn vài điều. Ý tôi là: gnu.org/software/emacs/manual/html_node/elisp/ mẹo nhưng điều này chỉ liên quan đến các quy trình async. Khi tôi về nhà, tôi sẽ xem xét các call-processnguồn, nhưng bây giờ tôi bắt đầu nghi ngờ rằng không có cách nào để giết nó khi hết thời gian.
wvxvw

Trên thực tế, tôi đã cố gắng tìm kiếm nó trên Github: github.com/emacs-mirror/emacs/blob/ và và không, tôi không thấy có bất kỳ mã nào có thể làm gì đó như đặt thời gian chờ cho quá trình.
wvxvw

Câu trả lời:


4

Trong khi call-processđang chạy, emacs sẽ xử lý các sự kiện, with-timeoutsẽ không hoạt động nếu không có điều này:

Thời gian chờ được kiểm tra bất cứ khi nào Emacs chờ đợi một loại sự kiện bên ngoài (chẳng hạn như đầu vào bàn phím, đầu vào từ các quy trình con hoặc một thời gian nhất định); nếu chương trình lặp mà không chờ đợi theo bất kỳ cách nào, thời gian chờ sẽ không được phát hiện.

Bạn vẫn có thể sử dụng with-timeoutvới (bán) các quy trình đồng bộ.

Bạn thực sự sẽ sử dụng một quy trình không đồng bộ nhưng sẽ đồng bộ chờ trong khi nó đang chạy, Emacs sẽ xử lý các sự kiện khi bạn chạy sit-for, bạn có thể chạy trong 0 giây. Sau đó, bạn có thể sử dụng đối số hình thức hết thời gian chờ with-timeoutđể giết tiến trình nếu nó vẫn đang chạy khi hết thời gian chờ.

(with-current-buffer (get-buffer-create "*my-proc-buffer*")
  (let ((proc (start-process "myproc" (current-buffer) "bash" "-c" "sleep 4"))) ;; start an async process
    (with-timeout (2 (kill-process proc)) ;; on timeout, kill the process
      (while (process-live-p proc) ;; while process is running
        (sit-for .05)) ;; let emacs read events and run timmers (and check for timeout)
      (message "finished on time!!")))) ;; this will run only if there is no timeout

Tôi đang có một vấn đề nhỏ với điều này. Đầu ra của các proces không được đảm bảo nằm trong bộ đệm đầu ra sau khi vòng lặp kết thúc. Tôi đang làm việc xung quanh nó bằng cách gọi người khác (sit-for 0.2)sau whilevòng lặp, nhưng cảm thấy không ổn định. Có cách nào để biết rằng đầu ra đã được in trên bộ đệm không?
Malabarba

Tôi không chắc về điều đó. Tôi sẽ giả sử rằng nếu bạn nhấn vào thời gian chờ, quá trình không được thực hiện bằng mọi cách vì vậy đầu ra không liên quan. Bạn đang làm gì để đầu ra vẫn cần thiết ngay cả sau khi hết thời gian? Bạn có khả năng có thể chuyển sang sử dụng bộ lọc quy trình và giết quá trình chỉ X giây trôi qua mà không có đầu ra thay vì sau X giây bất kể là gì.
Jordon Biondo

Xin lỗi, tôi đã không rõ ràng. Tôi không quan tâm đến đầu ra khi hết thời gian. Tôi đang nói rằng đầu ra không được in ngay lập tức sau khi quá trình kết thúc thành công .
Malabarba

Tôi nghĩ vấn đề là (sit-for 0), emacs dành quá nhiều thời gian để cho quá trình chạy và không đủ lắng nghe các sự kiện và chèn văn bản vào bộ đệm. Khi tôi thay đổi để (sit-for .05)mọi thứ hoạt động tốt hơn và tất cả văn bản đều vào bộ đệm của tôi. Ngay cả đối với một quá trình ngắn 0,05 giây không phải là một chi phí liên quan.
Jordon Biondo

Tôi không quá lo lắng về tình trạng quá tải trong tình huống này. Quá trình này được gọi là 5-8 lần và toàn bộ hoạt động là một hoạt động tương tác đã mất ít nhất vài giây, do đó, 1 giây nữa sẽ không tạo ra nhiều sự khác biệt. Điều làm tôi lo lắng một chút là sự ổn định, bởi vì tôi đã phải sử dụng (sit-for 0.2)cho các bài kiểm tra địa phương của mình để vượt qua, và thậm chí sau đó khi tôi đã thay đổi các bài kiểm tra travis đã thất bại.
Malabarba

4

Bạn có thể đạt được điều này bằng cách chỉ cần thêm một lệnh gọi hết thời gian GNU vào lệnh shell của bạn, mà các chu vi cần phải biết bất kỳ chi tiết nào về hành vi của Emacs. Ví dụ: chạy:

$ timeout 5 sleep 10

Sẽ quay lại sau 5 giây chứ không phải 10 (hết thời gian nhấn Ctrl-C một cách hiệu quả cho bạn).


Cảm ơn, tôi có thể phải đi với tùy chọn này nếu tôi không thể đạt được sự ổn định với tùy chọn khác. Tuy nhiên, tôi không muốn dựa vào một tiện ích khác, để nó cũng hoạt động trên Windows.
Malabarba
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.