Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

m2. fails to capture full output in WSL2 #240

Open
trinhdhk opened this issue Sep 24, 2024 · 0 comments
Open

m2. fails to capture full output in WSL2 #240

trinhdhk opened this issue Sep 24, 2024 · 0 comments

Comments

@trinhdhk
Copy link

trinhdhk commented Sep 24, 2024

Issue: for complicated gb with huge outputs, m2. may fail to fully parse due to writing lag.

Context in some settings with limited writing speed and/or some hindrance in connection between M2 and m2r, readLines may fail to parse. This happens obviously in WSL2.

Code to reproduce

# Create a matrix and fill it by row
X <- matrix(values, nrow = m, ncol = n, byrow = TRUE)
# Create the matrix
# X <- outer(1:m, 1:n, Vectorize(function(i, j) sprintf("x%02d%02d", i, j)))
# X <- matrix(c("a","b","c","d","e", "f"), nrow = 2, byrow = TRUE)
# Display the matrix
print(X)

# Number of terms in the equation
k <- m * n

# Initialize the equation vector
equation <- character(k)

# Loop to generate the equations
for (k in 1:((m)*n)) {
  q <- floor((k - 1) / n) + 1
  r <- ifelse(k %% n == 0, n, k %% n)
  
  equation[k] <- ""
  if (A[q,r] != 0)
    # Swapped the order of loops here
  {for (i in 1:n) {
    for (j in 1:m) {
      if (A[j,r] != 0) {
        if (A[j,i] != 0)
        {  if (nchar(equation[k]) > 0) {
          equation[k] <- paste0(equation[k], "+")
        }
          equation[k] <- paste0(equation[k], n,"*", X[q, r], "*", X[j, i])}}
    }
    if (A[q,i] != 0) {equation[k] <- paste0(equation[k], "-", X[q,i])}
  }}
  if(A[q,r] == 0) {equation[k] <- paste0(equation[k], X[q,r])}
}
for (k in ((m)*n+1):((m+1)*n)) {
  q <- floor((k - 1) / n) + 1
  r <- ifelse(k %% n == 0, n, k %% n)
  equation[k] <- "-1"
  for (j in 1:m) {
    if (A[j,r] != 0) {
      if (nchar(equation[k]) > 0) {
        equation[k] <- paste0(equation[k], "+")
      }
      equation[k] <- paste0(equation[k], n,"*",  X[j, r])}
  }
}


x <- as.vector(X)
x <- x[x != ""]
equation <- equation[equation != ""]

# Solve the equation


library(m2r)
m2r::ring_(x, coefring = "QQ")
gb(equation)

Expected result Return the solution
Actual result: Err out if (tokens[i] == "{") Missing value where TRUE/FALSE needed

This is due to a bug in m2. at output <- paste(readLines(get_m2_connection(), numlines), collapse = "\n"). It assumes conn has been fully written when the first line has been. However, in some niche situations as mentioned above, the second line has not been written yet. Result in an empty string.
Note that this happened in WSL2, not WSL1 or real Linux. And maybe(?) hardware-specific. Perhaps it has something to do with the virtual disk writing speed?

Workaround: add a loop to readLines:

ntry <- 0
repeat{
    output <- paste(readLines(get_m2_connection(), numlines), 
                    collapse = "\n")
    ntry <- ntry + 1
    Sys.sleep(getOption('mym2.readlag', 1e-3))
    if (ntry == 10000 || nchar(output)>0) break
 }

Current hack (if this package is abandoned) or not fixed or WSL2 unsupported:

# Change this to speed up or slow down the lag in readLines
options(mym2.readlag=5e-4)

mym2 = function (code, timeout = -1) {
  start_m2()
  if (code == "") 
    return("")
  
  writeLines(code, get_m2_connection())
  i <- 0
  outinfo <- NULL
  repeat {
    outinfo <- readLines(get_m2_connection(), 1)
    Sys.sleep(5e-4)
    if (length(outinfo) > 0) 
      break
    i <- i + 1
    if (timeout > 0 && i >= timeout * 2000) {
      break
    }
    else {
      Sys.sleep(5e-04)
    }
  }
 
  if (length(outinfo) > 0) {
    info <- strsplit(outinfo, " ", fixed = TRUE)[[1]]
    retcode <- strtoi(info[1])
    numlines <- strtoi(info[2])
    m2_name <- info[3]
    m2_class <- info[4]
    m2_class_class <- info[5]
  }
  else {
    tools::pskill(get_m2_procid(), tools::SIGINT)
    Sys.sleep(0.01)
    retcode <- -1L
    numlines <- -1L
  }

  ntry <- 0
  repeat{
    output <- paste(readLines(get_m2_connection(), numlines), 
                    collapse = "\n")
    ntry <- ntry + 1
    Sys.sleep(getOption('mym2.readlag', 1e-3))
    if (ntry == 10000 || nchar(output)>0) break
  }
  
  if (retcode == -1L) {
    stop_m2()
    stop("Command timed out, M2 connection lost")
  }
  else if (retcode == 1L) {
    stop(output, call. = FALSE)
  }
  else if (retcode == 2L) {
    output <- NULL
  }

  m2_structure(m2_name = m2_name, m2_class = "m2_pointer", 
               m2_meta = list(ext_str = output, m2_class = m2_class, 
                              m2_class_class = m2_class_class))
}

unlockBinding('m2.',asNamespace('m2r'))
assignInNamespace(x = 'm2.', value= mym2, asNamespace('m2r'))
@trinhdhk trinhdhk changed the title readLines fails to capture full output due to slow writing speed in WSL2 m2. fails to capture full output due to slow writing speed in WSL2 Sep 24, 2024
@trinhdhk trinhdhk changed the title m2. fails to capture full output due to slow writing speed in WSL2 m2. fails to capture full output in WSL2 Sep 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant