Skip to content

%dofuture% interferes with sink()? #776

@pglpm

Description

@pglpm

I'm calling the package Nimble from a foreach() loop with %dofuture%. Nimble outputs some messages, which I'd like to be redirected to log files, together with other messages generated with cat(). Nimble seems to be using the message() function, here is its code

I try to achieve this by opening a connection to the log file and redirecting sink() there. This approach worked with the doParallel backend, but the future backend keeps on sending the messages from Nimble or message() to the main R session.

Is this a bug? Or should I approach my goal differently?

Example with future:

library(`foreach`)
library(`doFuture`)
library('nimble')

future::plan('multisession', workers = 2)

foreach(i = 1:2) %dofuture% {
        outcon <- file(paste0('testout', i, '.log'), open = 'w') # open file for writing
        sink(outcon, type = c("output"))
        sink(outcon, type = c("message"))

        nimble::messageIfVerbose('nimble message') # message from Nimble
        message('\nmessage message\n')
        cat('\ncat message\n')
        
        sink(NULL, type = c("output"))
        sink(NULL, type = c("message"))
        close(outcon)
        i
    }
future::plan('sequential')

in this case the "cat message" correctly appears in each testout....log file, but the "nimble message" and the output from message() are displayed in the main R session.

Compare with doParallel:

library(`foreach`)
library(`doParallel`)
library('nimble')

cl <- parallel::makeCluster(2)
doParallel::registerDoParallel(cl)

foreach(i = 1:2) %dopar% {
        outcon <- file(paste0('testout', i, '.log'), open = 'w')
        sink(outcon, type = c("output"))
        sink(outcon, type = c("message"))

        nimble::messageIfVerbose('nimble message')
        message('\nmessage message\n')
        cat('\ncat message\n')

        sink(NULL, type = c("output"))
        sink(NULL, type = c("message"))
        close(outcon)
        i
    }
foreach::registerDoSEQ()
parallel::stopCluster(cl)

In this case all three messages appear in the log file.

I would expect the code with future to behave in a similar way as the one with doParallel, redirecting both messages to the log file.

Session information

> sessionInfo()
R version 4.4.3 (2025-02-28)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 20.04.6 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/liblapack.so.3;  LAPACK version 3.9.0

locale:
 [1] LC_CTYPE=en_GB.UTF-8    LC_NUMERIC=C            LC_TIME=en_SE.UTF-8    
 [4] LC_COLLATE=C            LC_MONETARY=C           LC_MESSAGES=en_GB.UTF-8
 [7] LC_PAPER=en_GB.UTF-8    LC_NAME=C               LC_ADDRESS=C           
[10] LC_TELEPHONE=C          LC_MEASUREMENT=C        LC_IDENTIFICATION=C    

time zone: Europe/Oslo
tzcode source: system (glibc)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] inferno_0.2.1  doFuture_1.0.2 future_1.40.0  foreach_1.5.2 

loaded via a namespace (and not attached):
 [1] doParallel_1.0.17   cli_3.6.4           rlang_1.1.6         listenv_0.9.1      
 [5] future.apply_1.11.3 rngtools_1.5.2      pracma_2.4.4        nimble_1.3.0       
 [9] grid_4.4.3          lifecycle_1.0.4     numDeriv_2016.8-1.1 doRNG_1.8.6.2      
[13] compiler_4.4.3      codetools_0.2-20    igraph_2.1.4        coda_0.19-4.1      
[17] pkgconfig_2.0.3     lattice_0.22-7      digest_0.6.37       R6_2.6.1           
[21] parallelly_1.43.0   parallel_4.4.3      magrittr_2.0.3      tools_4.4.3        
[25] iterators_1.0.14    globals_0.16.3     

> future::futureSessionInfo()
*** Package versions
future 1.40.0, parallelly 1.43.0, parallel 4.4.3, globals 0.16.3, listenv 0.9.1

*** Allocations
availableCores():
           system /proc/self/status    cgroups.cpuset             nproc 
               16                16                16                16 
availableWorkers():
$cgroups.cpuset
 [1] "localhost" "localhost" "localhost" "localhost" "localhost" "localhost"
 [7] "localhost" "localhost" "localhost" "localhost" "localhost" "localhost"
[13] "localhost" "localhost" "localhost" "localhost"

$nproc
 [1] "localhost" "localhost" "localhost" "localhost" "localhost" "localhost"
 [7] "localhost" "localhost" "localhost" "localhost" "localhost" "localhost"
[13] "localhost" "localhost" "localhost" "localhost"

$system
 [1] "localhost" "localhost" "localhost" "localhost" "localhost" "localhost"
 [7] "localhost" "localhost" "localhost" "localhost" "localhost" "localhost"
[13] "localhost" "localhost" "localhost" "localhost"


*** Settings
- future.plan=<not set>
- future.fork.multithreading.enable=<not set>
- future.globals.maxSize=<not set>
- future.globals.onReference=<not set>
- future.resolve.recursive=<not set>
- future.rng.onMisuse=<not set>
- future.wait.timeout=<not set>
- future.wait.interval=<not set>
- future.wait.alpha=<not set>
- future.startup.script=FALSE

*** Backends
Number of workers: 1
List of future strategies:
1. sequential:
   - args: function (..., gc = FALSE, earlySignal = FALSE, envir = parent.frame(), workers = "<NULL>")
   - tweaked: FALSE
   - call: future::plan("sequential")

*** Basic tests
Main R session details:
     pid     r sysname            release
1 394319 4.4.3   Linux 5.15.0-136-generic
                                               version nodename machine   login
1 #147~20.04.1-Ubuntu SMP Wed Mar 19 16:13:14 UTC 2025  host001  x86_64 user001
     user effective_user
1 user001        user001
Worker R session details:
  worker    pid     r sysname            release
1      1 394319 4.4.3   Linux 5.15.0-136-generic
                                               version nodename machine   login
1 #147~20.04.1-Ubuntu SMP Wed Mar 19 16:13:14 UTC 2025  host001  x86_64 user001
     user effective_user
1 user001        user001
Number of unique worker PIDs: 1 (as expected)

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions