1 2#' @useDynLib processx, .registration = TRUE, .fixes = "c_" 3NULL 4 5## Workaround an R CMD check false positive 6dummy_r6 <- function() R6::R6Class 7 8#' External process 9#' 10#' @description 11#' Managing external processes from R is not trivial, and this 12#' class aims to help with this deficiency. It is essentially a small 13#' wrapper around the `system` base R function, to return the process 14#' id of the started process, and set its standard output and error 15#' streams. The process id is then used to manage the process. 16#' 17#' @param n Number of characters or lines to read. 18#' @param grace Currently not used. 19#' @param close_connections Whether to close standard input, standard 20#' output, standard error connections and the poll connection, after 21#' killing the process. 22#' @param timeout Timeout in milliseconds, for the wait or the I/O 23#' polling. 24#' 25#' @section Batch files: 26#' Running Windows batch files (`.bat` or `.cmd` files) may be complicated 27#' because of the `cmd.exe` command line parsing rules. For example you 28#' cannot easily have whitespace in both the command (path) and one of the 29#' arguments. To work around these limitations you need to start a 30#' `cmd.exe` shell explicitly and use its `call` command. For example: 31#' 32#' ```r 33#' process$new("cmd.exe", c("/c", "call", bat_file, "arg 1", "arg 2")) 34#' ``` 35#' 36#' This works even if `bat_file` contains whitespace characters. 37#' 38#' @section Polling: 39#' The `poll_io()` function polls the standard output and standard 40#' error connections of a process, with a timeout. If there is output 41#' in either of them, or they are closed (e.g. because the process exits) 42#' `poll_io()` returns immediately. 43#' 44#' In addition to polling a single process, the [poll()] function 45#' can poll the output of several processes, and returns as soon as any 46#' of them has generated output (or exited). 47#' 48#' @section Cleaning up background processes: 49#' processx kills processes that are not referenced any more (if `cleanup` 50#' is set to `TRUE`), or the whole subprocess tree (if `cleanup_tree` is 51#' also set to `TRUE`). 52#' 53#' The cleanup happens when the references of the processes object are 54#' garbage collected. To clean up earlier, you can call the `kill()` or 55#' `kill_tree()` method of the process(es), from an `on.exit()` expression, 56#' or an error handler: 57#' ```r 58#' process_manager <- function() { 59#' on.exit({ 60#' try(p1$kill(), silent = TRUE) 61#' try(p2$kill(), silent = TRUE) 62#' }, add = TRUE) 63#' p1 <- process$new("sleep", "3") 64#' p2 <- process$new("sleep", "10") 65#' p1$wait() 66#' p2$wait() 67#' } 68#' process_manager() 69#' ``` 70#' 71#' If you interrupt `process_manager()` or an error happens then both `p1` 72#' and `p2` are cleaned up immediately. Their connections will also be 73#' closed. The same happens at a regular exit. 74#' 75#' @export 76#' @examplesIf identical(Sys.getenv("IN_PKGDOWN"), "true") 77#' p <- process$new("sleep", "2") 78#' p$is_alive() 79#' p 80#' p$kill() 81#' p$is_alive() 82#' 83#' p <- process$new("sleep", "1") 84#' p$is_alive() 85#' Sys.sleep(2) 86#' p$is_alive() 87 88process <- R6::R6Class( 89 "process", 90 cloneable = FALSE, 91 public = list( 92 93 #' @description 94 #' Start a new process in the background, and then return immediately. 95 #' 96 #' @return R6 object representing the process. 97 #' @param command Character scalar, the command to run. 98 #' Note that this argument is not passed to a shell, so no 99 #' tilde-expansion or variable substitution is performed on it. 100 #' It should not be quoted with [base::shQuote()]. See 101 #' [base::normalizePath()] for tilde-expansion. If you want to run 102 #' `.bat` or `.cmd` files on Windows, make sure you read the 103 #' 'Batch files' section above. 104 #' @param args Character vector, arguments to the command. They will be 105 #' passed to the process as is, without a shell transforming them, 106 #' They don't need to be escaped. 107 #' @param stdin What to do with the standard input. Possible values: 108 #' * `NULL`: set to the _null device_, i.e. no standard input is 109 #' provided; 110 #' * a file name, use this file as standard input; 111 #' * `"|"`: create a (writeable) connection for stdin. 112 #' * `""` (empty string): inherit it from the main R process. If the 113 #' main R process does not have a standard input stream, e.g. in 114 #' RGui on Windows, then an error is thrown. 115 #' @param stdout What to do with the standard output. Possible values: 116 #' * `NULL`: discard it; 117 #' * a string, redirect it to this file; 118 #' * `"|"`: create a connection for it. 119 #' * `""` (empty string): inherit it from the main R process. If the 120 #' main R process does not have a standard output stream, e.g. in 121 #' RGui on Windows, then an error is thrown. 122 #' @param stderr What to do with the standard error. Possible values: 123 #' * `NULL`: discard it; 124 #' * a string, redirect it to this file; 125 #' * `"|"`: create a connection for it; 126 #' * `"2>&1"`: redirect it to the same connection (i.e. pipe or file) 127 #' as `stdout`. `"2>&1"` is a way to keep standard output and error 128 #' correctly interleaved. 129 #' * `""` (empty string): inherit it from the main R process. If the 130 #' main R process does not have a standard error stream, e.g. in 131 #' RGui on Windows, then an error is thrown. 132 #' @param pty Whether to create a pseudo terminal (pty) for the 133 #' background process. This is currently only supported on Unix 134 #' systems, but not supported on Solaris. 135 #' If it is `TRUE`, then the `stdin`, `stdout` and `stderr` arguments 136 #' must be `NULL`. If a pseudo terminal is created, then processx 137 #' will create pipes for standard input and standard output. There is 138 #' no separate pipe for standard error, because there is no way to 139 #' distinguish between stdout and stderr on a pty. Note that the 140 #' standard output connection of the pty is _blocking_, so we always 141 #' poll the standard output connection before reading from it using 142 #' the `$read_output()` method. Also, because `$read_output_lines()` 143 #' could still block if no complete line is available, this function 144 #' always fails if the process has a pty. Use `$read_output()` to 145 #' read from ptys. 146 #' @param pty_options Unix pseudo terminal options, a named list. see 147 #' [default_pty_options()] for details and defaults. 148 #' @param connections A list of processx connections to pass to the 149 #' child process. This is an experimental feature currently. 150 #' @param poll_connection Whether to create an extra connection to the 151 #' process that allows polling, even if the standard input and 152 #' standard output are not pipes. If this is `NULL` (the default), 153 #' then this connection will be only created if standard output and 154 #' standard error are not pipes, and `connections` is an empty list. 155 #' If the poll connection is created, you can query it via 156 #' `p$get_poll_connection()` and it is also included in the response 157 #' to `p$poll_io()` and [poll()]. The numeric file descriptor of the 158 #' poll connection comes right after `stderr` (2), and the 159 #' connections listed in `connections`. 160 #' @param env Environment variables of the child process. If `NULL`, 161 #' the parent's environment is inherited. On Windows, many programs 162 #' cannot function correctly if some environment variables are not 163 #' set, so we always set `HOMEDRIVE`, `HOMEPATH`, `LOGONSERVER`, 164 #' `PATH`, `SYSTEMDRIVE`, `SYSTEMROOT`, `TEMP`, `USERDOMAIN`, 165 #' `USERNAME`, `USERPROFILE` and `WINDIR`. To append new environment 166 #' variables to the ones set in the current process, specify 167 #' `"current"` in `env`, without a name, and the appended ones with 168 #' names. The appended ones can overwrite the current ones. 169 #' @param cleanup Whether to kill the process when the `process` 170 #' object is garbage collected. 171 #' @param cleanup_tree Whether to kill the process and its child 172 #' process tree when the `process` object is garbage collected. 173 #' @param wd Working directory of the process. It must exist. 174 #' If `NULL`, then the current working directory is used. 175 #' @param echo_cmd Whether to print the command to the screen before 176 #' running it. 177 #' @param supervise Whether to register the process with a supervisor. 178 #' If `TRUE`, the supervisor will ensure that the process is 179 #' killed when the R process exits. 180 #' @param windows_verbatim_args Whether to omit quoting the arguments 181 #' on Windows. It is ignored on other platforms. 182 #' @param windows_hide_window Whether to hide the application's window 183 #' on Windows. It is ignored on other platforms. 184 #' @param windows_detached_process Whether to use the 185 #' `DETACHED_PROCESS` flag on Windows. If this is `TRUE`, then 186 #' the child process will have no attached console, even if the 187 #' parent had one. 188 #' @param encoding The encoding to assume for `stdin`, `stdout` and 189 #' `stderr`. By default the encoding of the current locale is 190 #' used. Note that `processx` always reencodes the output of the 191 #' `stdout` and `stderr` streams in UTF-8 currently. 192 #' If you want to read them without any conversion, on all platforms, 193 #' specify `"UTF-8"` as encoding. 194 #' @param post_process An optional function to run when the process has 195 #' finished. Currently it only runs if `$get_result()` is called. 196 #' It is only run once. 197 198 initialize = function(command = NULL, args = character(), 199 stdin = NULL, stdout = NULL, stderr = NULL, pty = FALSE, 200 pty_options = list(), connections = list(), poll_connection = NULL, 201 env = NULL, cleanup = TRUE, cleanup_tree = FALSE, wd = NULL, 202 echo_cmd = FALSE, supervise = FALSE, windows_verbatim_args = FALSE, 203 windows_hide_window = FALSE, windows_detached_process = !cleanup, 204 encoding = "", post_process = NULL) 205 206 process_initialize(self, private, command, args, stdin, 207 stdout, stderr, pty, pty_options, connections, 208 poll_connection, env, cleanup, cleanup_tree, wd, 209 echo_cmd, supervise, windows_verbatim_args, 210 windows_hide_window, windows_detached_process, 211 encoding, post_process), 212 213 #' @description 214 #' Cleanup method that is called when the `process` object is garbage 215 #' collected. If requested so in the process constructor, then it 216 #' eliminates all processes in the process's subprocess tree. 217 218 finalize = function() { 219 if (!is.null(private$tree_id) && private$cleanup_tree && 220 ps::ps_is_supported()) self$kill_tree() 221 }, 222 223 #' @description 224 #' Terminate the process. It also terminate all of its child 225 #' processes, except if they have created a new process group (on Unix), 226 #' or job object (on Windows). It returns `TRUE` if the process 227 #' was terminated, and `FALSE` if it was not (because it was 228 #' already finished/dead when `processx` tried to terminate it). 229 230 kill = function(grace = 0.1, close_connections = TRUE) 231 process_kill(self, private, grace, close_connections), 232 233 #' @description 234 #' Process tree cleanup. It terminates the process 235 #' (if still alive), together with any child (or grandchild, etc.) 236 #' processes. It uses the _ps_ package, so that needs to be installed, 237 #' and _ps_ needs to support the current platform as well. Process tree 238 #' cleanup works by marking the process with an environment variable, 239 #' which is inherited in all child processes. This allows finding 240 #' descendents, even if they are orphaned, i.e. they are not connected 241 #' to the root of the tree cleanup in the process tree any more. 242 #' `$kill_tree()` returns a named integer vector of the process ids that 243 #' were killed, the names are the names of the processes (e.g. `"sleep"`, 244 #' `"notepad.exe"`, `"Rterm.exe"`, etc.). 245 246 kill_tree = function(grace = 0.1, close_connections = TRUE) 247 process_kill_tree(self, private, grace, close_connections), 248 249 #' @description 250 #' Send a signal to the process. On Windows only the 251 #' `SIGINT`, `SIGTERM` and `SIGKILL` signals are interpreted, 252 #' and the special 0 signal. The first three all kill the process. The 0 253 #' signal returns `TRUE` if the process is alive, and `FALSE` 254 #' otherwise. On Unix all signals are supported that the OS supports, 255 #' and the 0 signal as well. 256 #' @param signal An integer scalar, the id of the signal to send to 257 #' the process. See [tools::pskill()] for the list of signals. 258 259 signal = function(signal) 260 process_signal(self, private, signal), 261 262 #' @description 263 #' Send an interrupt to the process. On Unix this is a 264 #' `SIGINT` signal, and it is usually equivalent to pressing CTRL+C at 265 #' the terminal prompt. On Windows, it is a CTRL+BREAK keypress. 266 #' Applications may catch these events. By default they will quit. 267 268 interrupt = function() 269 process_interrupt(self, private), 270 271 #' @description 272 #' Query the process id. 273 #' @return Integer scalar, the process id of the process. 274 275 get_pid = function() 276 process_get_pid(self, private), 277 278 #' @description Check if the process is alive. 279 #' @return Logical scalar. 280 281 is_alive = function() 282 process_is_alive(self, private), 283 284 #' @description 285 #' Wait until the process finishes, or a timeout happens. 286 #' Note that if the process never finishes, and the timeout is infinite 287 #' (the default), then R will never regain control. In some rare cases, 288 #' `$wait()` might take a bit longer than specified to time out. This 289 #' happens on Unix, when another package overwrites the processx 290 #' `SIGCHLD` signal handler, after the processx process has started. 291 #' One such package is parallel, if used with fork clusters, e.g. 292 #' through `parallel::mcparallel()`. 293 #' @return It returns the process itself, invisibly. 294 295 wait = function(timeout = -1) 296 process_wait(self, private, timeout), 297 298 #' @description 299 #' `$get_exit_status` returns the exit code of the process if it has 300 #' finished and `NULL` otherwise. On Unix, in some rare cases, the exit 301 #' status might be `NA`. This happens if another package (or R itself) 302 #' overwrites the processx `SIGCHLD` handler, after the processx process 303 #' has started. In these cases processx cannot determine the real exit 304 #' status of the process. One such package is parallel, if used with 305 #' fork clusters, e.g. through the `parallel::mcparallel()` function. 306 307 get_exit_status = function() 308 process_get_exit_status(self, private), 309 310 #' @description 311 #' `format(p)` or `p$format()` creates a string representation of the 312 #' process, usually for printing. 313 314 format = function() 315 process_format(self, private), 316 317 #' @description 318 #' `print(p)` or `p$print()` shows some information about the 319 #' process on the screen, whether it is running and it's process id, etc. 320 321 print = function() 322 process_print(self, private), 323 324 #' @description 325 #' `$get_start_time()` returns the time when the process was 326 #' started. 327 328 get_start_time = function() 329 process_get_start_time(self, private), 330 331 #' @description 332 #' `$is_supervised()` returns whether the process is being tracked by 333 #' supervisor process. 334 335 is_supervised = function() 336 process_is_supervised(self, private), 337 338 #' @description 339 #' `$supervise()` if passed `TRUE`, tells the supervisor to start 340 #' tracking the process. If `FALSE`, tells the supervisor to stop 341 #' tracking the process. Note that even if the supervisor is disabled 342 #' for a process, if it was started with `cleanup = TRUE`, the process 343 #' will still be killed when the object is garbage collected. 344 #' @param status Whether to turn on of off the supervisor for this 345 #' process. 346 347 supervise = function(status) 348 process_supervise(self, private, status), 349 350 ## Output 351 352 #' @description 353 #' `$read_output()` reads from the standard output connection of the 354 #' process. If the standard output connection was not requested, then 355 #' then it returns an error. It uses a non-blocking text connection. This 356 #' will work only if `stdout="|"` was used. Otherwise, it will throw an 357 #' error. 358 359 read_output = function(n = -1) 360 process_read_output(self, private, n), 361 362 #' @description 363 #' `$read_error()` is similar to `$read_output`, but it reads 364 #' from the standard error stream. 365 366 read_error = function(n = -1) 367 process_read_error(self, private, n), 368 369 #' @description 370 #' `$read_output_lines()` reads lines from standard output connection 371 #' of the process. If the standard output connection was not requested, 372 #' then it returns an error. It uses a non-blocking text connection. 373 #' This will work only if `stdout="|"` was used. Otherwise, it will 374 #' throw an error. 375 376 read_output_lines = function(n = -1) 377 process_read_output_lines(self, private, n), 378 379 #' @description 380 #' `$read_error_lines()` is similar to `$read_output_lines`, but 381 #' it reads from the standard error stream. 382 383 read_error_lines = function(n = -1) 384 process_read_error_lines(self, private, n), 385 386 #' @description 387 #' `$is_incomplete_output()` return `FALSE` if the other end of 388 #' the standard output connection was closed (most probably because the 389 #' process exited). It return `TRUE` otherwise. 390 391 is_incomplete_output = function() 392 process_is_incompelete_output(self, private), 393 394 #' @description 395 #' `$is_incomplete_error()` return `FALSE` if the other end of 396 #' the standard error connection was closed (most probably because the 397 #' process exited). It return `TRUE` otherwise. 398 399 is_incomplete_error = function() 400 process_is_incompelete_error(self, private), 401 402 #' @description 403 #' `$has_input_connection()` return `TRUE` if there is a connection 404 #' object for standard input; in other words, if `stdout="|"`. It returns 405 #' `FALSE` otherwise. 406 407 has_input_connection = function() 408 process_has_input_connection(self, private), 409 410 #' @description 411 #' `$has_output_connection()` returns `TRUE` if there is a connection 412 #' object for standard output; in other words, if `stdout="|"`. It returns 413 #' `FALSE` otherwise. 414 415 has_output_connection = function() 416 process_has_output_connection(self, private), 417 418 #' @description 419 #' `$has_error_connection()` returns `TRUE` if there is a connection 420 #' object for standard error; in other words, if `stderr="|"`. It returns 421 #' `FALSE` otherwise. 422 423 has_error_connection = function() 424 process_has_error_connection(self, private), 425 426 #' @description 427 #' `$has_poll_connection()` return `TRUE` if there is a poll connection, 428 #' `FALSE` otherwise. 429 430 has_poll_connection = function() 431 process_has_poll_connection(self, private), 432 433 #' @description 434 #' `$get_input_connection()` returns a connection object, to the 435 #' standard input stream of the process. 436 437 get_input_connection = function() 438 process_get_input_connection(self, private), 439 440 #' @description 441 #' `$get_output_connection()` returns a connection object, to the 442 #' standard output stream of the process. 443 444 get_output_connection = function() 445 process_get_output_connection(self, private), 446 447 #' @description 448 #' `$get_error_conneciton()` returns a connection object, to the 449 #' standard error stream of the process. 450 451 get_error_connection = function() 452 process_get_error_connection(self, private), 453 454 #' @description 455 #' `$read_all_output()` waits for all standard output from the process. 456 #' It does not return until the process has finished. 457 #' Note that this process involves waiting for the process to finish, 458 #' polling for I/O and potentially several `readLines()` calls. 459 #' It returns a character scalar. This will return content only if 460 #' `stdout="|"` was used. Otherwise, it will throw an error. 461 462 read_all_output = function() 463 process_read_all_output(self, private), 464 465 #' @description 466 #' `$read_all_error()` waits for all standard error from the process. 467 #' It does not return until the process has finished. 468 #' Note that this process involves waiting for the process to finish, 469 #' polling for I/O and potentially several `readLines()` calls. 470 #' It returns a character scalar. This will return content only if 471 #' `stderr="|"` was used. Otherwise, it will throw an error. 472 473 read_all_error = function() 474 process_read_all_error(self, private), 475 476 #' @description 477 #' `$read_all_output_lines()` waits for all standard output lines 478 #' from a process. It does not return until the process has finished. 479 #' Note that this process involves waiting for the process to finish, 480 #' polling for I/O and potentially several `readLines()` calls. 481 #' It returns a character vector. This will return content only if 482 #' `stdout="|"` was used. Otherwise, it will throw an error. 483 484 read_all_output_lines = function() 485 process_read_all_output_lines(self, private), 486 487 #' @description 488 #' `$read_all_error_lines()` waits for all standard error lines from 489 #' a process. It does not return until the process has finished. 490 #' Note that this process involves waiting for the process to finish, 491 #' polling for I/O and potentially several `readLines()` calls. 492 #' It returns a character vector. This will return content only if 493 #' `stderr="|"` was used. Otherwise, it will throw an error. 494 495 read_all_error_lines = function() 496 process_read_all_error_lines(self, private), 497 498 #' @description 499 #' `$write_input()` writes the character vector (separated by `sep`) to 500 #' the standard input of the process. It will be converted to the specified 501 #' encoding. This operation is non-blocking, and it will return, even if 502 #' the write fails (because the write buffer is full), or if it suceeds 503 #' partially (i.e. not the full string is written). It returns with a raw 504 #' vector, that contains the bytes that were not written. You can supply 505 #' this raw vector to `$write_input()` again, until it is fully written, 506 #' and then the return value will be `raw(0)` (invisibly). 507 #' 508 #' @param str Character or raw vector to write to the standard input 509 #' of the process. If a character vector with a marked encoding, 510 #' it will be converted to `encoding`. 511 #' @param sep Separator to add between `str` elements if it is a 512 #' character vector. It is ignored if `str` is a raw vector. 513 #' @return Leftover text (as a raw vector), that was not written. 514 515 write_input = function(str, sep = "\n") 516 process_write_input(self, private, str, sep), 517 518 #' @description 519 #' `$get_input_file()` if the `stdin` argument was a filename, 520 #' this returns the absolute path to the file. If `stdin` was `"|"` or 521 #' `NULL`, this simply returns that value. 522 523 get_input_file = function() 524 process_get_input_file(self, private), 525 526 #' @description 527 #' `$get_output_file()` if the `stdout` argument was a filename, 528 #' this returns the absolute path to the file. If `stdout` was `"|"` or 529 #' `NULL`, this simply returns that value. 530 531 get_output_file = function() 532 process_get_output_file(self, private), 533 534 #' @description 535 #' `$get_error_file()` if the `stderr` argument was a filename, 536 #' this returns the absolute path to the file. If `stderr` was `"|"` or 537 #' `NULL`, this simply returns that value. 538 539 get_error_file = function() 540 process_get_error_file(self, private), 541 542 #' @description 543 #' `$poll_io()` polls the process's connections for I/O. See more in 544 #' the _Polling_ section, and see also the [poll()] function 545 #' to poll on multiple processes. 546 547 poll_io = function(timeout) 548 process_poll_io(self, private, timeout), 549 550 #' @description 551 #' `$get_poll_connetion()` returns the poll connection, if the process has 552 #' one. 553 554 get_poll_connection = function() 555 process_get_poll_connection(self, private), 556 557 #' @description 558 #' `$get_result()` returns the result of the post processesing function. 559 #' It can only be called once the process has finished. If the process has 560 #' no post-processing function, then `NULL` is returned. 561 562 get_result = function() 563 process_get_result(self, private), 564 565 #' @description 566 #' `$as_ps_handle()` returns a [ps::ps_handle] object, corresponding to 567 #' the process. 568 569 as_ps_handle = function() 570 process_as_ps_handle(self, private), 571 572 #' @description 573 #' Calls [ps::ps_name()] to get the process name. 574 575 get_name = function() 576 ps_method(ps::ps_name, self), 577 578 #' @description 579 #' Calls [ps::ps_exe()] to get the path of the executable. 580 581 get_exe = function() 582 ps_method(ps::ps_exe, self), 583 584 #' @description 585 #' Calls [ps::ps_cmdline()] to get the command line. 586 587 get_cmdline = function() 588 ps_method(ps::ps_cmdline, self), 589 590 #' @description 591 #' Calls [ps::ps_status()] to get the process status. 592 593 get_status = function() 594 ps_method(ps::ps_status, self), 595 596 #' @description 597 #' calls [ps::ps_username()] to get the username. 598 599 get_username = function() 600 ps_method(ps::ps_username, self), 601 602 #' @description 603 #' Calls [ps::ps_cwd()] to get the current working directory. 604 605 get_wd = function() 606 ps_method(ps::ps_cwd, self), 607 608 #' @description 609 #' Calls [ps::ps_cpu_times()] to get CPU usage data. 610 611 get_cpu_times = function() 612 ps_method(ps::ps_cpu_times, self), 613 614 #' @description 615 #' Calls [ps::ps_memory_info()] to get memory data. 616 617 get_memory_info = function() 618 ps_method(ps::ps_memory_info, self), 619 620 #' @description 621 #' Calls [ps::ps_suspend()] to suspend the process. 622 623 suspend = function() 624 ps_method(ps::ps_suspend, self), 625 626 #' @description 627 #' Calls [ps::ps_resume()] to resume a suspended process. 628 629 resume = function() 630 ps_method(ps::ps_resume, self) 631 ), 632 633 private = list( 634 635 command = NULL, # Save 'command' argument here 636 args = NULL, # Save 'args' argument here 637 cleanup = NULL, # cleanup argument 638 cleanup_tree = NULL, # cleanup_tree argument 639 stdin = NULL, # stdin argument or stream 640 stdout = NULL, # stdout argument or stream 641 stderr = NULL, # stderr argument or stream 642 pty = NULL, # whether we should create a PTY 643 pty_options = NULL, # various PTY options 644 pstdin = NULL, # the original stdin argument 645 pstdout = NULL, # the original stdout argument 646 pstderr = NULL, # the original stderr argument 647 cleanfiles = NULL, # which temp stdout/stderr file(s) to clean up 648 wd = NULL, # working directory (or NULL for current) 649 starttime = NULL, # timestamp of start 650 echo_cmd = NULL, # whether to echo the command 651 windows_verbatim_args = NULL, 652 windows_hide_window = NULL, 653 654 status = NULL, # C file handle 655 656 supervised = FALSE, # Whether process is tracked by supervisor 657 658 stdin_pipe = NULL, 659 stdout_pipe = NULL, 660 stderr_pipe = NULL, 661 poll_pipe = NULL, 662 663 encoding = "", 664 665 env = NULL, 666 667 connections = list(), 668 669 post_process = NULL, 670 post_process_result = NULL, 671 post_process_done = FALSE, 672 673 tree_id = NULL, 674 675 get_short_name = function() 676 process_get_short_name(self, private), 677 close_connections = function() 678 process_close_connections(self, private) 679 ) 680) 681 682## See the C source code for a discussion about the implementation 683## of these methods 684 685process_wait <- function(self, private, timeout) { 686 "!DEBUG process_wait `private$get_short_name()`" 687 rethrow_call_with_cleanup( 688 c_processx_wait, private$status, 689 as.integer(timeout), 690 private$get_short_name() 691 ) 692 invisible(self) 693} 694 695process_is_alive <- function(self, private) { 696 "!DEBUG process_is_alive `private$get_short_name()`" 697 rethrow_call(c_processx_is_alive, private$status, private$get_short_name()) 698} 699 700process_get_exit_status <- function(self, private) { 701 "!DEBUG process_get_exit_status `private$get_short_name()`" 702 rethrow_call(c_processx_get_exit_status, private$status, 703 private$get_short_name()) 704} 705 706process_signal <- function(self, private, signal) { 707 "!DEBUG process_signal `private$get_short_name()` `signal`" 708 rethrow_call(c_processx_signal, private$status, as.integer(signal), 709 private$get_short_name()) 710} 711 712process_interrupt <- function(self, private) { 713 "!DEBUG process_interrupt `private$get_short_name()`" 714 if (os_type() == "windows") { 715 pid <- as.character(self$get_pid()) 716 st <- run(get_tool("interrupt"), c(pid, "c"), error_on_status = FALSE) 717 if (st$status == 0) TRUE else FALSE 718 } else { 719 rethrow_call(c_processx_interrupt, private$status, 720 private$get_short_name()) 721 } 722} 723 724process_kill <- function(self, private, grace, close_connections) { 725 "!DEBUG process_kill '`private$get_short_name()`', pid `self$get_pid()`" 726 ret <- rethrow_call(c_processx_kill, private$status, as.numeric(grace), 727 private$get_short_name()) 728 if (close_connections) private$close_connections() 729 ret 730} 731 732process_kill_tree <- function(self, private, grace, close_connections) { 733 "!DEBUG process_kill_tree '`private$get_short_name()`', pid `self$get_pid()`" 734 if (!ps::ps_is_supported()) { 735 throw(new_not_implemented_error( 736 "kill_tree is not supported on this platform")) 737 } 738 739 ret <- get("ps_kill_tree", asNamespace("ps"))(private$tree_id) 740 if (close_connections) private$close_connections() 741 ret 742} 743 744process_get_start_time <- function(self, private) { 745 format_unix_time(private$starttime) 746} 747 748process_get_pid <- function(self, private) { 749 rethrow_call(c_processx_get_pid, private$status) 750} 751 752process_is_supervised <- function(self, private) { 753 private$supervised 754} 755 756process_supervise <- function(self, private, status) { 757 if (status && !self$is_supervised()) { 758 supervisor_watch_pid(self$get_pid()) 759 private$supervised <- TRUE 760 761 } else if (!status && self$is_supervised()) { 762 supervisor_unwatch_pid(self$get_pid()) 763 private$supervised <- FALSE 764 } 765} 766 767process_get_result <- function(self, private) { 768 if (self$is_alive()) throw(new_error("Process is still alive")) 769 if (!private$post_process_done && is.function(private$post_process)) { 770 private$post_process_result <- private$post_process() 771 private$post_process_done <- TRUE 772 } 773 private$post_process_result 774} 775 776process_as_ps_handle <- function(self, private) { 777 ps::ps_handle(self$get_pid(), self$get_start_time()) 778} 779 780ps_method <- function(fun, self) { 781 fun(ps::ps_handle(self$get_pid(), self$get_start_time())) 782} 783 784process_close_connections <- function(self, private) { 785 for (f in c("stdin_pipe", "stdout_pipe", "stderr_pipe", "poll_pipe")) { 786 if (!is.null(p <- private[[f]])) { 787 rethrow_call(c_processx_connection_close, p) 788 } 789 } 790} 791 792#' Default options for pseudo terminals (ptys) 793#' 794#' @return Named list of default values of pty options. 795#' 796#' Options and default values: 797#' * `echo` whether to keep the echo on the terminal. `FALSE` turns echo 798#' off. 799#' * `rows` the (initial) terminal size, number of rows. 800#' * `cols` the (initial) terminal size, number of columns. 801#' 802#' @export 803 804default_pty_options <- function() { 805 list( 806 echo = FALSE, 807 rows = 25L, 808 cols = 80L 809 ) 810} 811