Skip to content

Commit 4457bbf

Browse files
authored
Merge pull request #522 from stan-dev/bugfix_clear_stdout_stderr_on_finish
Bugfix clearing stdout stderr on finish & cleanup
2 parents bee8254 + e44a0d0 commit 4457bbf

File tree

7 files changed

+71
-87
lines changed

7 files changed

+71
-87
lines changed

NEWS.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# cmdstanr 0.4.0.9000
22

3+
### Bug fixes
4+
5+
* Fixed bug that caused stdour/stderr not being read at the end of
6+
optimization. (#522)
7+
8+
### New features
9+
310
* Default directory changed to `.cmdstan` instead of `.cmdstanr` so that
411
CmdStanPy and CmdStanR can use the same CmdStan installations. Using `.cmdstanr`
512
will continue to be supported until version 1.0 but `install_cmdstan()` will now

R/data.R

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,7 @@ process_fitted_params <- function(fitted_params) {
243243
}
244244
)
245245
sampler_diagnostics <- tryCatch(
246-
fitted_params$sampler_diagnostics(),
247-
error = function(cond) {
248-
NULL
249-
}
246+
fitted_params$sampler_diagnostics()
250247
)
251248
paths <- draws_to_csv(draws, sampler_diagnostics)
252249
} else if (checkmate::test_r6(fitted_params, "CmdStanVB")) {

R/install.R

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ install_cmdstan <- function(dir = NULL,
154154
cmdstan_make_local(dir = dir_cmdstan, cpp_options = cpp_options, append = TRUE)
155155
version <- read_cmdstan_version(dir_cmdstan)
156156
if (os_is_windows()) {
157-
if (version >= "2.24" && R.version$major >= "4") {
157+
if (version >= "2.24" && R.version$major >= "4" && !("PRECOMPILED_HEADERS" %in% toupper(names(cpp_options)))) {
158158
# cmdstan 2.24 can use precompiled headers with RTools 4.0 to speedup compiling
159159
cmdstan_make_local(
160160
dir = dir_cmdstan,
@@ -371,36 +371,6 @@ build_cmdstan <- function(dir,
371371
)
372372
}
373373

374-
# Removes files that are used to simplify switching to using threading, opencl or mpi.
375-
clean_compile_helper_files <- function() {
376-
# remove main_.*.o files and model_header_.*.hpp.gch files
377-
files_to_remove <- c(
378-
list.files(
379-
path = file.path(cmdstan_path(), "src", "cmdstan"),
380-
pattern = "main.*\\.o$",
381-
full.names = TRUE
382-
),
383-
list.files(
384-
path = file.path(cmdstan_path(), "src", "cmdstan"),
385-
pattern = "main.*\\.d$",
386-
full.names = TRUE
387-
),
388-
list.files(
389-
path = file.path(cmdstan_path(), "stan", "src", "stan", "model"),
390-
pattern = "model_header.*\\.hpp.gch$",
391-
full.names = TRUE
392-
),
393-
list.files(
394-
path = file.path(cmdstan_path(), "stan", "src", "stan", "model"),
395-
pattern = "model_header.*\\.d$",
396-
full.names = TRUE
397-
)
398-
)
399-
if (!is.null(files_to_remove)) {
400-
file.remove(files_to_remove)
401-
}
402-
}
403-
404374
clean_cmdstan <- function(dir = cmdstan_path(),
405375
cores = getOption("mc.cores", 2),
406376
quiet = FALSE) {
@@ -414,13 +384,12 @@ clean_cmdstan <- function(dir = cmdstan_path(),
414384
error_on_status = FALSE,
415385
stderr_callback = function(x, p) { if (quiet) message(x) }
416386
)
417-
clean_compile_helper_files()
418387
}
419388

420389
build_example <- function(dir, cores, quiet, timeout) {
421390
processx::run(
422391
make_cmd(),
423-
args = c(paste0("-j", cores), cmdstan_ext("examples/bernoulli/bernoulli")),
392+
args = c(paste0("-j", cores), cmdstan_ext(file.path("examples", "bernoulli", "bernoulli"))),
424393
wd = dir,
425394
echo_cmd = is_verbose_mode(),
426395
echo = !quiet || is_verbose_mode(),

R/model.R

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -457,18 +457,7 @@ compile <- function(quiet = TRUE,
457457
}
458458
}
459459

460-
stancflags_val <- ""
461-
if (!is.null(include_paths)) {
462-
checkmate::assert_directory_exists(include_paths, access = "r")
463-
include_paths <- absolute_path(include_paths)
464-
include_paths <- paste0(include_paths, collapse = ",")
465-
if (cmdstan_version() >= "2.24") {
466-
include_paths_flag <- " --include-paths="
467-
} else {
468-
include_paths_flag <- " --include_paths="
469-
}
470-
stancflags_val <- paste0(stancflags_val, include_paths_flag, include_paths, " ")
471-
}
460+
stancflags_val <- include_paths_stanc3_args(include_paths)
472461

473462
if (pedantic) {
474463
stanc_options[["warn-pedantic"]] <- TRUE
@@ -491,7 +480,7 @@ compile <- function(quiet = TRUE,
491480
stanc_built_options <- c(stanc_built_options, paste0("--", option_name, "=", "'", stanc_options[[i]], "'"))
492481
}
493482
}
494-
stancflags_val <- paste0("STANCFLAGS += ", stancflags_val, paste0(stanc_built_options, collapse = " "))
483+
stancflags_val <- paste0("STANCFLAGS += ", stancflags_val, paste0(" ", stanc_built_options, collapse = " "))
495484
run_log <- processx::run(
496485
command = make_cmd(),
497486
args = c(tmp_exe,
@@ -612,18 +601,7 @@ check_syntax <- function(pedantic = FALSE,
612601
stanc_options[["warn-pedantic"]] <- TRUE
613602
}
614603

615-
stancflags_val <- NULL
616-
if (!is.null(include_paths)) {
617-
checkmate::assert_directory_exists(include_paths, access = "r")
618-
include_paths <- absolute_path(include_paths)
619-
include_paths <- paste0(include_paths, collapse = ",")
620-
if (cmdstan_version() >= "2.24") {
621-
include_paths_flag <- " --include-paths="
622-
} else {
623-
include_paths_flag <- " --include_paths="
624-
}
625-
stancflags_val <- trimws(paste0(include_paths_flag, include_paths, " "))
626-
}
604+
stancflags_val <- include_paths_stanc3_args(include_paths)
627605

628606
if (is.null(stanc_options[["name"]])) {
629607
stanc_options[["name"]] <- paste0(self$model_name(), "_model")
@@ -1394,3 +1372,19 @@ cpp_options_to_compile_flags <- function(cpp_options) {
13941372
}
13951373
cpp_built_options
13961374
}
1375+
1376+
include_paths_stanc3_args <- function(include_paths = NULL) {
1377+
stancflags <- NULL
1378+
if (!is.null(include_paths)) {
1379+
checkmate::assert_directory_exists(include_paths, access = "r")
1380+
include_paths <- absolute_path(include_paths)
1381+
include_paths <- paste0(include_paths, collapse = ",")
1382+
if (cmdstan_version() >= "2.24") {
1383+
include_paths_flag <- "--include-paths="
1384+
} else {
1385+
include_paths_flag <- "--include_paths="
1386+
}
1387+
stancflags <- paste0(stancflags, include_paths_flag, include_paths)
1388+
}
1389+
stancflags
1390+
}

R/run.R

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -364,10 +364,8 @@ check_target_exe <- function(exe) {
364364
procs$poll(0)
365365
for (chain_id in chains) {
366366
if (!procs$is_queued(chain_id)) {
367-
output <- procs$get_proc(chain_id)$read_output_lines()
368-
procs$process_output(output, chain_id)
369-
error_output <- procs$get_proc(chain_id)$read_error_lines()
370-
procs$process_error_output(error_output, chain_id)
367+
procs$process_output(chain_id)
368+
procs$process_error_output(chain_id)
371369
}
372370
}
373371
procs$set_active_procs(procs$num_alive())
@@ -424,10 +422,8 @@ CmdStanRun$set("private", name = "run_sample_", value = .run_sample)
424422
procs$poll(0)
425423
for (chain_id in chains) {
426424
if (!procs$is_queued(chain_id)) {
427-
output <- procs$get_proc(chain_id)$read_output_lines()
428-
procs$process_output(output, chain_id)
429-
error_output <- procs$get_proc(chain_id)$read_error_lines()
430-
procs$process_error_output(error_output, chain_id)
425+
procs$process_output(chain_id)
426+
procs$process_error_output(chain_id)
431427
}
432428
}
433429
procs$set_active_procs(procs$num_alive())
@@ -460,13 +456,13 @@ CmdStanRun$set("private", name = "run_generate_quantities_", value = .run_genera
460456
procs$wait(0.1)
461457
procs$poll(0)
462458
if (!procs$is_queued(id)) {
463-
output <- procs$get_proc(id)$read_output_lines()
464-
procs$process_output(output, id)
465-
error_output <- procs$get_proc(id)$read_error_lines()
466-
procs$process_error_output(error_output, id)
459+
procs$process_output(id)
460+
procs$process_error_output(id)
467461
}
468462
procs$set_active_procs(procs$num_alive())
469463
}
464+
procs$process_output(id)
465+
procs$process_error_output(id)
470466
successful_fit <- FALSE
471467
if (self$method() == "optimize") {
472468
if (procs$proc_state(id = id) > 3) {
@@ -651,10 +647,8 @@ CmdStanProcs <- R6::R6Class(
651647
if (self$is_still_working(id) && !self$is_queued(id) && !self$is_alive(id)) {
652648
# if the process just finished make sure we process all
653649
# input and mark the process finished
654-
output <- self$get_proc(id)$read_output_lines()
655-
self$process_output(output, id)
656-
error_output <- self$get_proc(id)$read_error_lines()
657-
self$process_error_output(error_output, id)
650+
self$process_output(id)
651+
self$process_error_output(id)
658652
self$mark_proc_stop(id)
659653
self$report_time(id)
660654
}
@@ -723,7 +717,8 @@ CmdStanProcs <- R6::R6Class(
723717
(grepl("A method must be specified!", line, perl = TRUE)) ||
724718
(grepl("is not a valid value for", line, perl = TRUE))
725719
},
726-
process_error_output = function(err_out, id) {
720+
process_error_output = function(id) {
721+
err_out <- self$get_proc(id)$read_error_lines()
727722
if (length(err_out)) {
728723
for (err_line in err_out) {
729724
private$proc_output_[[id]] <- c(private$proc_output_[[id]], err_line)
@@ -733,7 +728,8 @@ CmdStanProcs <- R6::R6Class(
733728
}
734729
}
735730
},
736-
process_output = function(out, id) {
731+
process_output = function(id) {
732+
out <- self$get_proc(id)$read_output_lines()
737733
if (length(out) == 0) {
738734
return(NULL)
739735
}
@@ -809,7 +805,8 @@ CmdStanMCMCProcs <- R6::R6Class(
809805
classname = "CmdStanMCMCProcs",
810806
inherit = CmdStanProcs,
811807
public = list(
812-
process_output = function(out, id) {
808+
process_output = function(id) {
809+
out <- self$get_proc(id)$read_output_lines()
813810
if (length(out) == 0) {
814811
return(invisible(NULL))
815812
}
@@ -843,7 +840,7 @@ CmdStanMCMCProcs <- R6::R6Class(
843840
next_state <- 3
844841
}
845842
if (state < 3 && grepl("Elapsed Time:", line, perl = TRUE)) {
846-
state <- 5 # 5 = end of samp+ling
843+
state <- 5 # 5 = end of sampling
847844
next_state <- 5
848845
}
849846
if (private$proc_state_[[id]] == 3 &&
@@ -968,7 +965,8 @@ CmdStanGQProcs <- R6::R6Class(
968965
}
969966
invisible(self)
970967
},
971-
process_output = function(out, id) {
968+
process_output = function(id) {
969+
out <- self$get_proc(id)$read_output_lines()
972970
if (length(out) == 0) {
973971
return(NULL)
974972
}

R/utils.R

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,7 @@ is_rosetta2 <- function() {
6060

6161
# Returns the type of make command to use to compile depending on the OS
6262
make_cmd <- function() {
63-
# CmdStan 2.21 introduced TBB that requires mingw32-make on Windows
64-
ver <- .cmdstanr$VERSION
65-
if (os_is_windows() && (is.null(ver) || ver >= "2.21")) {
63+
if (os_is_windows()) {
6664
"mingw32-make.exe"
6765
} else {
6866
"make"

tests/testthat/test-model-compile.R

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ test_that("compiling stops on hyphens in stanc_options", {
277277
test_that("compiling works with only names in list", {
278278
skip_on_cran()
279279
stan_file <- testing_stan_file("bernoulli")
280-
mod <- cmdstan_model(stan_file, stanc_options = list("warn-pedantic"), force_recompile = TRUE, quiet = FALSE)
280+
mod <- cmdstan_model(stan_file, stanc_options = list("warn-pedantic"), force_recompile = TRUE)
281281
checkmate::expect_r6(
282282
mod,
283283
"CmdStanModel"
@@ -461,3 +461,24 @@ test_that("cpp_options_to_compile_flags() works", {
461461
options = list()
462462
expect_equal(cpp_options_to_compile_flags(options), NULL)
463463
})
464+
465+
test_that("include_paths_stanc3_args() works", {
466+
expect_equal(include_paths_stanc3_args(), NULL)
467+
path_1 <- file.path(tempdir(), "folder1")
468+
if (!dir.exists(path_1)) {
469+
dir.create(path_1)
470+
}
471+
path_1 <- repair_path(path_1)
472+
expect_equal(include_paths_stanc3_args(path_1), paste0("--include-paths=", path_1))
473+
path_2 <- file.path(tempdir(), "folder2")
474+
if (!dir.exists(path_2)) {
475+
dir.create(path_2)
476+
}
477+
path_2 <- repair_path(path_2)
478+
expect_equal(
479+
include_paths_stanc3_args(c(path_1, path_2)),
480+
c(
481+
paste0("--include-paths=", path_1, ",", path_2)
482+
)
483+
)
484+
})

0 commit comments

Comments
 (0)