Re: [R-pkg-devel] safely allocate SEXP and handle failure

2023-09-21 Thread Ivan Krylov
В Thu, 21 Sep 2023 15:10:56 +0200
Jan Gorecki  пишет:

> Do you by any chance know any examples of using
> R_withCallingErrorHandler? Or could you modify your example to use
> this instead?

Calling handlers are different from exiting handlers established by
tryCatch. Instead of replacing the value of an expression that raised a
condition with the return value of the exiting handler, calling
handlers get an opportunity to clean up or invoke a so-called restart,
but when they return, the execution continues:

withCallingHandlers(stop("fatal"), error = function(cond) {
 writeLines("I'm a calling handler, this is my argument:")
 str(cond)
})
# I'm a calling handler, this is my argument:
# List of 2
#  $ message: chr "fatal"
#  $ call   : language withCallingHandlers(stop("fatal"), ...
#  - attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
# Error in withCallingHandlers(stop("fatal"), error = function(cond) { :
#   fatal

Since setting up restarts will involve calling into R, a complete
solution will involve much more code than R_tryCatchError.

-- 
Best regards,
Ivan

__
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel


Re: [R-pkg-devel] safely allocate SEXP and handle failure

2023-09-21 Thread Ivan Krylov
On Thu, 21 Sep 2023 09:46:26 +0200
Jan Gorecki  wrote:

> I would like to safely allocate R object from C. By safely I mean
> that, I can test if allocation succeeded or failed, and then raise
> exception myself.
> R_alloc and allocVector both raises exception straightaway, so I am
> not able to handle failed allocation myself.

All R objects are subject to garbage collection (as potential garbage
or at least as a source of information about live objects), so they
have to be allocated by talking to the GC. (This also means that
R_alloc() is not a good way to create new SEXPs.)

It's not that it's impossible to return a failure code on allocation
failures instead of performing a longjmp() away from your code, but
since the rest of error handling in R works this way, extension code
has to always be ready to be longjmp()'d away from at every R API call.

How about catching the exception instead?

struct alloc_args { SEXPTYPE type; R_xlen_t len; };

static SEXP do_allocate(void * arguments) {
 struct alloc_args * args = arguments;
 return allocVector(args->type, args->len);
}

static SEXP maybe_allocate(SEXPTYPE type, R_xlen_t len) {
 struct alloc_args args = { .type = type, .len = len };
 return R_tryCatchError(do_allocate, &args, NULL, NULL);
} // returns R_NilValue on failure via the default tryCatch handler

Code is untested but should work according to WRE:
https://cran.r-project.org/doc/manuals/R-exts.html#Condition-handling-and-cleanup-code

-- 
Best regards,
Ivan

__
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel


[R-pkg-devel] safely allocate SEXP and handle failure

2023-09-21 Thread Jan Gorecki
Dear pkg developers

I would like to safely allocate R object from C. By safely I mean
that, I can test if allocation succeeded or failed, and then raise
exception myself.
R_alloc and allocVector both raises exception straightaway, so I am
not able to handle failed allocation myself.
In plain C it is something like that:

int *x = malloc(nx*sizeof(int));
if (!x) {
  my_fun_to_set_exception_signal();
  free(x);
  return;
}

How can I do it for creating SEXP object?

Best Regards,
Jan Gorecki

__
R-package-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-package-devel