[Rd] Expected behaviour of is.unsorted?
Hi, I've read ?is.unsorted and searched. Have found a few items but nothing close, yet. Is the following expected? > is.unsorted(data.frame(1:2)) [1] FALSE > is.unsorted(data.frame(2:1)) [1] FALSE > is.unsorted(data.frame(1:2,3:4)) [1] TRUE > is.unsorted(data.frame(2:1,4:3)) [1] TRUE IIUC, is.unsorted is intended for atomic vectors only (description of x in ?is.unsorted). Indeed the C source (src/main/sort.c) contains an error message "only atomic vectors can be tested to be sorted". So that is the error message I expected to see in all cases above, since I know that data.frame is not an atomic vector. But there is also this in ?is.unsorted: "except for atomic vectors and objects with a class (where the >= or > method is used)" which I don't understand. Where >= or > is used by what, and where? I understand why the first two are FALSE (1 item of anything must be sorted). I don't understand the 3rd and 4th cases where length is 2: do_isunsorted seems to call lang3(install(".gtn"), x, CADR(args))). Does that fall back to TRUE for some reason? Matthew > sessionInfo() R version 2.15.0 (2012-03-30) Platform: x86_64-pc-mingw32/x64 (64-bit) locale: [1] LC_COLLATE=English_United Kingdom.1252 LC_CTYPE=English_United Kingdom.1252 [3] LC_MONETARY=English_United Kingdom.1252 LC_NUMERIC=C [5] LC_TIME=English_United Kingdom.1252 attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] data.table_1.8.0 loaded via a namespace (and not attached): [1] tools_2.15.0 __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
[Rd] giving a datasets list
Dear colleagues, I'm currently trying to improve my R package (PairedData) devoted to the analysis (and plotting) of paired data. For basic statistics teaching purposes, I would like to give a list of the most interesting datasets including paired data available in R packages (BSDA, HistData...) together with basic information like sample size, disciplinary field (psychology, medecine,...) and maybe main statistical features. Any idea for efficiently including this bit of information in a package? A special dataset? A vignette? A kind of help page? Thank you for any help, S. CHAMPELY Sports department Lyon 1 University France [[alternative HTML version deleted]] __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Expected behaviour of is.unsorted?
>> is.unsorted(data.frame(1:2)) > [1] FALSE >> is.unsorted(data.frame(2:1)) > [1] FALSE >> is.unsorted(data.frame(1:2,3:4)) > [1] TRUE >> is.unsorted(data.frame(2:1,4:3)) > [1] TRUE > > IIUC, is.unsorted is intended for atomic vectors only (description of x in > ?is.unsorted). Indeed the C source (src/main/sort.c) contains an error > message "only atomic vectors can be tested to be sorted". So that is the > error message I expected to see in all cases above, since I know that > data.frame is not an atomic vector. But there is also this in > ?is.unsorted: "except for atomic vectors and objects with a class (where > the >= or > method is used)" which I don't understand. Where >= or > is > used by what, and where? > > I understand why the first two are FALSE (1 item of anything must be > sorted). I don't understand the 3rd and 4th cases where length is 2: > do_isunsorted seems to call lang3(install(".gtn"), x, CADR(args))). Does > that fall back to TRUE for some reason? I've just been having similar worries with this today. The odd behaviour seems to be particular to data.frames. Compare for example, is.unsorted(list(1, 3, 2)) #NA is.unsorted(data.frame(1, 3, 2)) #FALSE is.unsorted(data.frame(1, 2, 3)) #TRUE IMHO, it would be clearer if is.unsorted either always returned NA for recursive objects of length 2 or more, or it called unlist to make it atomic. Either way, it should really provide some sort of warning about non-standard input. -- Regards, Richie live-analytics.com 4dpiecharts.com __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
[Rd] prcomp with previously scaled data: predict with 'newdata' wrong
Hello folks, it may be regarded as a user error to scale() your data prior to prcomp() instead of using its 'scale.' argument. However, it is a user thing that may happen and sounds a legitimate thing to do, but in that case predict() with 'newdata' can give wrong results: x <- scale(USArrests) sol <- prcomp(x) all.equal(predict(sol), predict(sol, newdata=x)) ## [1] "Mean relative difference: 0.9033485" Predicting with the same data gives different results than the original PCA of the data. The reason of this behaviour seems to be in these first lines of stats:::prcomp.default(): x <- scale(x, center = center, scale = scale.) cen <- attr(x, "scaled:center") sc <- attr(x, "scaled:scale") If input data 'x' have 'scaled:scale' attribute, it will be retained if scale() is called with argument "scale = FALSE" like is the case with default options in prcomp(). So scale(scale(x, scale = TRUE), scale = FALSE) will have the 'scaled:center' of the outer scale() (i.e, numerical zero), but the 'scaled:scale' of the inner scale(). Function princomp finds the 'scale' directly instead of looking at the attributes of the input data, and works like expected: sol <- princomp(x) all.equal(predict(sol), predict(sol, newdata=x)) ## [1] TRUE I don't have any nifty solution to this -- only checking the 'scale.' attribute and acting accordingly: sc <- if (scale.) attr(x, "scaled:scale") else FALSE Cheers, Jari Oksanen __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Expected behaviour of is.unsorted?
On 12-05-23 4:37 AM, Matthew Dowle wrote: Hi, I've read ?is.unsorted and searched. Have found a few items but nothing close, yet. Is the following expected? is.unsorted(data.frame(1:2)) [1] FALSE is.unsorted(data.frame(2:1)) [1] FALSE is.unsorted(data.frame(1:2,3:4)) [1] TRUE is.unsorted(data.frame(2:1,4:3)) [1] TRUE IIUC, is.unsorted is intended for atomic vectors only (description of x in ?is.unsorted). Indeed the C source (src/main/sort.c) contains an error message "only atomic vectors can be tested to be sorted". So that is the error message I expected to see in all cases above, since I know that data.frame is not an atomic vector. But there is also this in ?is.unsorted: "except for atomic vectors and objects with a class (where the>= or> method is used)" which I don't understand. Where>= or> is used by what, and where? If you look at the source, you will see that the basic test for classed objects is all(x[-1L] >= x[-length(x)]) (in the function base:::.gtn). This comparison doesn't really makes sense for dataframes, but it does seem to be backwards: that tests that x[2] >= x[1], x[3] >= x[2], etc., returning TRUE if all comparisons are TRUE: but that sounds like it should be is.sorted(), not is.unsorted(). Or is it my brain that is backwards? Duncan Murdoch I understand why the first two are FALSE (1 item of anything must be sorted). I don't understand the 3rd and 4th cases where length is 2: do_isunsorted seems to call lang3(install(".gtn"), x, CADR(args))). Does that fall back to TRUE for some reason? Matthew sessionInfo() R version 2.15.0 (2012-03-30) Platform: x86_64-pc-mingw32/x64 (64-bit) locale: [1] LC_COLLATE=English_United Kingdom.1252 LC_CTYPE=English_United Kingdom.1252 [3] LC_MONETARY=English_United Kingdom.1252 LC_NUMERIC=C [5] LC_TIME=English_United Kingdom.1252 attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] data.table_1.8.0 loaded via a namespace (and not attached): [1] tools_2.15.0 __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] prcomp with previously scaled data: predict with 'newdata' wrong
To fix myself: the stupid solution I suggested won't work as 'scale.' need not be TRUE or FALSE, but it can be a vector of scales. The following looks like being able to handle this, but is not transparent nor elegant: sc <- if (isTRUE(scale.)) attr(x, "scaled:scale") else scale. I trust you find an elegant solution (if you think this is worth fixing). Cheers, Jari Oksanen PS. Sorry for the top posting: cannot help with the email system I have in my work desktop. From: r-devel-boun...@r-project.org [r-devel-boun...@r-project.org] on behalf of Jari Oksanen [jari.oksa...@oulu.fi] Sent: 23 May 2012 13:51 To: r-de...@stat.math.ethz.ch Subject: [Rd] prcomp with previously scaled data: predict with 'newdata' wrong Hello folks, it may be regarded as a user error to scale() your data prior to prcomp() instead of using its 'scale.' argument. However, it is a user thing that may happen and sounds a legitimate thing to do, but in that case predict() with 'newdata' can give wrong results: x <- scale(USArrests) sol <- prcomp(x) all.equal(predict(sol), predict(sol, newdata=x)) ## [1] "Mean relative difference: 0.9033485" Predicting with the same data gives different results than the original PCA of the data. The reason of this behaviour seems to be in these first lines of stats:::prcomp.default(): x <- scale(x, center = center, scale = scale.) cen <- attr(x, "scaled:center") sc <- attr(x, "scaled:scale") If input data 'x' have 'scaled:scale' attribute, it will be retained if scale() is called with argument "scale = FALSE" like is the case with default options in prcomp(). So scale(scale(x, scale = TRUE), scale = FALSE) will have the 'scaled:center' of the outer scale() (i.e, numerical zero), but the 'scaled:scale' of the inner scale(). Function princomp finds the 'scale' directly instead of looking at the attributes of the input data, and works like expected: sol <- princomp(x) all.equal(predict(sol), predict(sol, newdata=x)) ## [1] TRUE I don't have any nifty solution to this -- only checking the 'scale.' attribute and acting accordingly: sc <- if (scale.) attr(x, "scaled:scale") else FALSE Cheers, Jari Oksanen __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] [R] how to remove the 'promise' attribute of an R object (.Random.seed)?
OK, I switched to r-devel. I'm caching the random seed by saving and lazy loading .Random.seed, so I think it should always be valid (except that it becomes a promise which is essentially an integer vector). The complete process is as follows: set.seed(1) # R generates .Random.seed now tools:::makeLazyLoadDB(globalenv(), 'random_db', variables = '.Random.seed') lazyLoad('random_db') rnorm(1) # Error in rnorm(1) : # .Random.seed is not an integer vector but of type 'promise' As I explained earlier, the purpose is for caching when an Sweave document involves with RNG; instead of running set.seed() again, I just lazy-load the seed. I'm not sure if this is a convincing enough application. You might frown on the use of :::, though. Thanks! Regards, Yihui -- Yihui Xie Phone: 515-294-2465 Web: http://yihui.name Department of Statistics, Iowa State University 2215 Snedecor Hall, Ames, IA On Wed, May 23, 2012 at 1:03 AM, Prof Brian Ripley wrote: > On 22/05/2012 22:26, Yihui Xie wrote: >> >> I did not use delayedAssign() directly; I was using lazyLoad() and >> .Random.seed was saved in a database. The real story out there is the >> caching of my knitr package -- lazyLoad() was used to speed up the >> compilation of Sweave documents. >> >> I know lazyLoad() is supposed to be used only by R itself, but it is >> very helpful for the purpose of caching as well. >> >> Or is it possible to change the code in src/main/RNG.c so that the >> seed is force()d if it is a promise? > > > It is possible, but we need to be convinced that it is desirable. The main > point is that you should not be setting .Random.seed (see its help page), > and all the ways R itself sets it create a object of the correct internal > type. The test is there because of people who failed to follow the advice > and set it incorrectly (usually as a double vector). > > If you want to make a case for a change, R-devel would be the appropriate > list and you would need to explain in detail why you thinking setting > .Random.seed is appropriate and exactly how you do it. > > >> Anyway, I can use save() and load() in this case instead of lazyLoad() >> if the above is not going to happen. Thanks a lot! >> >> Regards, >> Yihui >> -- >> Yihui Xie >> Phone: 515-294-2465 Web: http://yihui.name >> Department of Statistics, Iowa State University >> 2215 Snedecor Hall, Ames, IA >> >> >> On Tue, May 22, 2012 at 12:49 PM, wrote: >>> >>> On Tue, 22 May 2012, Yihui Xie wrote: >>> Hi, The problem arises when I lazyLoad() the .Random.seed from a previously saved database. To simplify the process of reproducing the problem, see the example below: ## this assignment may not really make sense, but illustrates the problem delayedAssign('.Random.seed', 1L) typeof(.Random.seed) # [1] "integer" rnorm(1) # Error in rnorm(1) : # .Random.seed is not an integer vector but of type 'promise' typeof(.Random.seed) # [1] "integer" So there must be an "attribute" "promise" somewhere attached to .Random.seed, and I cannot find it. The R function typeof() does not reveal it, but the TYPEOF() function in src/main/RNG.c says it is a 'promise'. My question is, how to make R use the real value of .Random.seed instead of complaining about the promise? Thanks! >>> >>> >>> >>> Siple answer: Don't creat the promise in the first place, i.e. don't >>> use delayedAssign. >>> >>> What is the real context where this arises? Knowing that may help us >>> decide whether the internals should address this possibility. >>> >>> Best, >>> >>> luke >>> Regards, Yihui -- Yihui Xie Phone: 515-294-2465 Web: http://yihui.name Department of Statistics, Iowa State University 2215 Snedecor Hall, Ames, IA __ r-h...@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code. >>> >>> -- >>> Luke Tierney >>> Chair, Statistics and Actuarial Science >>> Ralph E. Wareham Professor of Mathematical Sciences >>> University of Iowa Phone: 319-335-3386 >>> Department of Statistics and Fax: 319-335-3017 >>> Actuarial Science >>> 241 Schaeffer Hall email: luke-tier...@uiowa.edu >>> Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu >> >> >> __ >> r-h...@r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide >> http://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code. > > > > -- > Brian D. Ripley, rip...@stats.ox.ac.uk > Professor of Applied Statistics, ht
Re: [Rd] [R] how to remove the 'promise' attribute of an R object (.Random.seed)?
I'm not persuaded at this point that we want to support use of the lazy loading infrastructure outside the core as we might want to change it in the future. But the principle that promises are an internal implementation detail that should be as invisible at possible at the user level suggest that this should be changed, so R-devel and R-patched now force promises in this case. There are a number of other cases in the sources that may have similar issues. It would be good to check them over and handle any that need handling in a systematic way. I don't have time to do that now but I'll put it in my queue. luke On Wed, 23 May 2012, Yihui Xie wrote: OK, I switched to r-devel. I'm caching the random seed by saving and lazy loading .Random.seed, so I think it should always be valid (except that it becomes a promise which is essentially an integer vector). The complete process is as follows: set.seed(1) # R generates .Random.seed now tools:::makeLazyLoadDB(globalenv(), 'random_db', variables = '.Random.seed') lazyLoad('random_db') rnorm(1) # Error in rnorm(1) : # .Random.seed is not an integer vector but of type 'promise' As I explained earlier, the purpose is for caching when an Sweave document involves with RNG; instead of running set.seed() again, I just lazy-load the seed. I'm not sure if this is a convincing enough application. You might frown on the use of :::, though. Thanks! Regards, Yihui -- Yihui Xie Phone: 515-294-2465 Web: http://yihui.name Department of Statistics, Iowa State University 2215 Snedecor Hall, Ames, IA On Wed, May 23, 2012 at 1:03 AM, Prof Brian Ripley wrote: On 22/05/2012 22:26, Yihui Xie wrote: I did not use delayedAssign() directly; I was using lazyLoad() and .Random.seed was saved in a database. The real story out there is the caching of my knitr package -- lazyLoad() was used to speed up the compilation of Sweave documents. I know lazyLoad() is supposed to be used only by R itself, but it is very helpful for the purpose of caching as well. Or is it possible to change the code in src/main/RNG.c so that the seed is force()d if it is a promise? It is possible, but we need to be convinced that it is desirable. The main point is that you should not be setting .Random.seed (see its help page), and all the ways R itself sets it create a object of the correct internal type. The test is there because of people who failed to follow the advice and set it incorrectly (usually as a double vector). If you want to make a case for a change, R-devel would be the appropriate list and you would need to explain in detail why you thinking setting .Random.seed is appropriate and exactly how you do it. Anyway, I can use save() and load() in this case instead of lazyLoad() if the above is not going to happen. Thanks a lot! Regards, Yihui -- Yihui Xie Phone: 515-294-2465 Web: http://yihui.name Department of Statistics, Iowa State University 2215 Snedecor Hall, Ames, IA On Tue, May 22, 2012 at 12:49 PM, wrote: On Tue, 22 May 2012, Yihui Xie wrote: Hi, The problem arises when I lazyLoad() the .Random.seed from a previously saved database. To simplify the process of reproducing the problem, see the example below: ## this assignment may not really make sense, but illustrates the problem delayedAssign('.Random.seed', 1L) typeof(.Random.seed) # [1] "integer" rnorm(1) # Error in rnorm(1) : # .Random.seed is not an integer vector but of type 'promise' typeof(.Random.seed) # [1] "integer" So there must be an "attribute" "promise" somewhere attached to .Random.seed, and I cannot find it. The R function typeof() does not reveal it, but the TYPEOF() function in src/main/RNG.c says it is a 'promise'. My question is, how to make R use the real value of .Random.seed instead of complaining about the promise? Thanks! Siple answer: Don't creat the promise in the first place, i.e. don't use delayedAssign. What is the real context where this arises? Knowing that may help us decide whether the internals should address this possibility. Best, luke Regards, Yihui -- Yihui Xie Phone: 515-294-2465 Web: http://yihui.name Department of Statistics, Iowa State University 2215 Snedecor Hall, Ames, IA __ r-h...@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code. -- Luke Tierney Chair, Statistics and Actuarial Science Ralph E. Wareham Professor of Mathematical Sciences University of Iowa Phone: 319-335-3386 Department of Statistics and Fax: 319-335-3017 Actuarial Science 241 Schaeffer Hall email: luke-tier...@uiowa.edu Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu __ r-h...@r-project.org mailing list https://stat.ethz.ch/mailman/listin
Re: [Rd] Capturing signals from within external libs
Simon, Thanks for the clarifying example. I fear my current set up fails the test for 'no R calls', so I think I am stuck on the ugly variant for my current challenge, but I will be able to use this in other places. Thanks again, Jeff On 5/22/12 4:45 PM, "Simon Urbanek" wrote: >Jeff, > >On May 22, 2012, at 4:31 PM, Jeffrey Ryan wrote: > >> I have a continuous loop running in an external library that I am >>calling >> from C (R API). This loop is processing events in real time with the >> possibility of significant lag between events. >> >> When processing an event, I can make use of R_CheckUserInterrupt, but >> while the external library code is waiting on a new event, I don't have >>an >> opportunity to call this - my entry points are only on events. >> > >Assuming that while in the library there are no R calls (important!), you >can use setjmp/longjmp to branch your code depending on whether you raise >an interrupt or not (see below). This also makes sure that you process >things on the R side properly > >Another alternative is to run your library call on a separate thread and >have R wait for the result. In that case you don't need to mess with >interrupts since your library code will run separately from R. The >downside is that you need to mess with threads which may or may not be an >issue depending on the complexity of your code and whether you want it to >be cross-platform or not. > >Cheers, >Simon > > >Example code: > >#include >#include >#include > >#include >#include /* only needed if you use >R_interrupts_pending */ > >static jmp_buf jenv; > >static void my_int(int sig) { > longjmp(jenv, 1); /* this also restores the interrupt handlers */ >} > >SEXP my_R_function(...) { > >if (setjmp(jenv) == 0) { /* enter your protected code */ > void (*old_sig)(int); > old_sig = signal(SIGINT, my_int); > /* call your library here */ > /* restore original INT handler */ > signal(SIGINT, old_sig); >} else { /* this will get called on interrupt */ > /* you can do what you want - you're back to R-safe code here, so you >can either raise an error or return from your function */ > /* if you want to trigger regular R interrupt handling, use this: */ > R_interrupts_pending = 1; > R_CheckUserInterrupt(); > /* the above should not return */ >} > > > >> I can capture a SIGINT by redefining signal(SIGINT, myhandler) before >> calling the lib, but I am somewhat at a loss in terms of what I can do >> within the handler that would let me pass control back to R. >> >> void myhandler (int s) { >> error("interrupt caught!"); >> } >> >> Works, but I am sure it isn't supposed to. In fact I know it is wrong, >> since after interrupting once SIGINTs are subsequently ignored, even if >>I >> reset the signal to the original one (as returned by the first call to >> signal). >> >> Currently I can exit(1) of course, but that is tragically bad form IMO, >> though will work in my situation. >> >> In short, what is the proper way to handle SIGINT in external code that >>is >> called from R, that allows R to handle the signal. Thoughts or >> suggestions appreciated. >> >> Thanks, >> Jeff >> >> __ >> R-devel@r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel >> >> > __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] test suites for packages
I use svUnit, too. I put a kind of standard skeleton into my packages that has a packagename.unittest () function that will run all svUnit tests (if svUnit is available). This function returns NA if svUnit is not available, invisible (TRUE) if all tests are passed and stops otherwise. Which will cause R CMD check to fail. My test directory contains one single tests.R file with the two lines: library (packagename) packagename.unittest () which gives me e.g.: Running the tests in ‘tests/tests.R’ failed. Last 13 lines of output: only logical matrix subscripts are allowed in replacement * : ...) ... **ERROR** Error in `[<-.data.frame`(`*tmp*`, x.na, value = NA) : only logical matrix subscripts are allowed in replacement kind timingtime unit msg test(kernelpls.fit)OK 0.009 2012-05-23 14:38:49 test(scale)OK 0.009 2012-05-23 14:38:49 test(.ldapreproc) **ERROR** 0.007 2012-05-23 14:38:49 test(pcalda) OK 0.003 2012-05-23 14:38:49 Error in errorLog(summarize = FALSE) : 0 failure(s) and 1 error(s) Calls: cbmodels.unittest -> errorLog Execution halted While the 13 lines may not be enough if there are lots of tests, I can easily run packagename.unittest () in an interactive session and start tracking down the problem from there. Claudia Am 18.05.2012 17:28, schrieb Cook, Malcolm: > svUnit - is Runit compatible and provides some IDE integration and report > generation and easy syntax for defining tests. > > I find it works a treat, and fits very nicely with my R coding/packaging > style (which also uses inlinedocs for easy package creation). > > --Malcolm Cook > > > On 5/17/12 9:10 AM, "Whit Armstrong" wrote: > >> Can anyone share some opinions on test suites for R packages? >> >> I'm looking at testthat and RUnit. Does anyone have strong opinions on >> either of those. >> >> Any additional packages I should consider? >> >> Thanks, >> Whit >> >> __ >> R-devel@r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel > > __ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel -- Claudia Beleites Spectroscopy/Imaging Institute of Photonic Technology Albert-Einstein-Str. 9 07745 Jena Germany email: claudia.belei...@ipht-jena.de phone: +49 3641 206-133 fax: +49 2641 206-399 __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Capturing signals from within external libs
On May 23, 2012, at 12:40 PM, Jeffrey Ryan wrote: > Simon, > > Thanks for the clarifying example. I fear my current set up fails the > test for 'no R calls', Well, but in that case you already have interrupt points so I'm not sure what is the problem? I thought the whole point is that you have long processing in some 3rd party library where you can't call R API so that's why you need the hack in the first place ... > so I think I am stuck on the ugly variant for my > current challenge, but I will be able to use this in other places. > > Thanks again, > Jeff > > On 5/22/12 4:45 PM, "Simon Urbanek" wrote: > >> Jeff, >> >> On May 22, 2012, at 4:31 PM, Jeffrey Ryan wrote: >> >>> I have a continuous loop running in an external library that I am >>> calling >>> from C (R API). This loop is processing events in real time with the >>> possibility of significant lag between events. >>> >>> When processing an event, I can make use of R_CheckUserInterrupt, but >>> while the external library code is waiting on a new event, I don't have >>> an >>> opportunity to call this - my entry points are only on events. >>> >> >> Assuming that while in the library there are no R calls (important!), you >> can use setjmp/longjmp to branch your code depending on whether you raise >> an interrupt or not (see below). This also makes sure that you process >> things on the R side properly >> >> Another alternative is to run your library call on a separate thread and >> have R wait for the result. In that case you don't need to mess with >> interrupts since your library code will run separately from R. The >> downside is that you need to mess with threads which may or may not be an >> issue depending on the complexity of your code and whether you want it to >> be cross-platform or not. >> >> Cheers, >> Simon >> >> >> Example code: >> >> #include >> #include >> #include >> >> #include >> #include /* only needed if you use >> R_interrupts_pending */ >> >> static jmp_buf jenv; >> >> static void my_int(int sig) { >> longjmp(jenv, 1); /* this also restores the interrupt handlers */ >> } >> >> SEXP my_R_function(...) { >> >> if (setjmp(jenv) == 0) { /* enter your protected code */ >> void (*old_sig)(int); >> old_sig = signal(SIGINT, my_int); >> /* call your library here */ >> /* restore original INT handler */ >> signal(SIGINT, old_sig); >> } else { /* this will get called on interrupt */ >> /* you can do what you want - you're back to R-safe code here, so you >> can either raise an error or return from your function */ >> /* if you want to trigger regular R interrupt handling, use this: */ >> R_interrupts_pending = 1; >> R_CheckUserInterrupt(); >> /* the above should not return */ >> } >> >> >> >>> I can capture a SIGINT by redefining signal(SIGINT, myhandler) before >>> calling the lib, but I am somewhat at a loss in terms of what I can do >>> within the handler that would let me pass control back to R. >>> >>> void myhandler (int s) { >>> error("interrupt caught!"); >>> } >>> >>> Works, but I am sure it isn't supposed to. In fact I know it is wrong, >>> since after interrupting once SIGINTs are subsequently ignored, even if >>> I >>> reset the signal to the original one (as returned by the first call to >>> signal). >>> >>> Currently I can exit(1) of course, but that is tragically bad form IMO, >>> though will work in my situation. >>> >>> In short, what is the proper way to handle SIGINT in external code that >>> is >>> called from R, that allows R to handle the signal. Thoughts or >>> suggestions appreciated. >>> >>> Thanks, >>> Jeff >>> >>> __ >>> R-devel@r-project.org mailing list >>> https://stat.ethz.ch/mailman/listinfo/r-devel >>> >>> >> > > > __ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel
Re: [Rd] Capturing signals from within external libs
Simon, Very likely butchered my initial problem explanation. The issue is that I make a call to a library, something like: SEXP my_fun() { ... CB = MyCallback("XYZ"); /* this contains callback functions that in turn use R */ externalLibCall(CB); /* infinite loop that won't return as it is capturing streaming data */ /* we never get here */ Return(R_NilValue); } My callbacks look something like on_event_A () { R_CheckUserInterrupt(): evalRFunctionFromC(); } But event_A only gets called when a new message arrives. When a new message arrives the on_event_A gets called from within the external library code (hence calling R), but only when a message arrives. At this point R_CheckUserInterrupt() works just fine. The problem is when the external process is waiting on a new message. I have no entry to check whether or not a message is available, nothing akin to select(). Basically I only get control in my callback when a new message happens. So if there is no new message (in the context above it is a message/tick from an exchange), the process spins/waits/not too sure what happens internally, but the net result is I don't see anything. I am waiting. It is at this point that I want to force an interrupt. My current solution is just to redefine as my SIGINT handler before the externalLibCall call, with an ungraceful exit() internal to it. Dirty, but lets me break. In the ideal world I would be returned to the R prompt, but it isn't overly critical in this application since it is being run more or less headless as is. The other problem, which makes me cringe of course, is that this is all further complicated by the fact that it is not just C, but C++ and running on Win64 ;-) I tried not to mention that of course ... Your insights are very appreciated, and I now have further knowledge into making this work in other applications, but my hope for this one is dwindling. Best, Jeff On 5/23/12 11:49 AM, "Simon Urbanek" wrote: > >On May 23, 2012, at 12:40 PM, Jeffrey Ryan wrote: > >> Simon, >> >> Thanks for the clarifying example. I fear my current set up fails the >> test for 'no R calls', > >Well, but in that case you already have interrupt points so I'm not sure >what is the problem? I thought the whole point is that you have long >processing in some 3rd party library where you can't call R API so that's >why you need the hack in the first place ... > > >> so I think I am stuck on the ugly variant for my >> current challenge, but I will be able to use this in other places. >> >> Thanks again, >> Jeff >> >> On 5/22/12 4:45 PM, "Simon Urbanek" wrote: >> >>> Jeff, >>> >>> On May 22, 2012, at 4:31 PM, Jeffrey Ryan wrote: >>> I have a continuous loop running in an external library that I am calling from C (R API). This loop is processing events in real time with the possibility of significant lag between events. When processing an event, I can make use of R_CheckUserInterrupt, but while the external library code is waiting on a new event, I don't have an opportunity to call this - my entry points are only on events. >>> >>> Assuming that while in the library there are no R calls (important!), >>>you >>> can use setjmp/longjmp to branch your code depending on whether you >>>raise >>> an interrupt or not (see below). This also makes sure that you process >>> things on the R side properly >>> >>> Another alternative is to run your library call on a separate thread >>>and >>> have R wait for the result. In that case you don't need to mess with >>> interrupts since your library code will run separately from R. The >>> downside is that you need to mess with threads which may or may not be >>>an >>> issue depending on the complexity of your code and whether you want it >>>to >>> be cross-platform or not. >>> >>> Cheers, >>> Simon >>> >>> >>> Example code: >>> >>> #include >>> #include >>> #include >>> >>> #include >>> #include /* only needed if you use >>> R_interrupts_pending */ >>> >>> static jmp_buf jenv; >>> >>> static void my_int(int sig) { >>> longjmp(jenv, 1); /* this also restores the interrupt handlers */ >>> } >>> >>> SEXP my_R_function(...) { >>> >>> if (setjmp(jenv) == 0) { /* enter your protected code */ >>> void (*old_sig)(int); >>> old_sig = signal(SIGINT, my_int); >>> /* call your library here */ >>> /* restore original INT handler */ >>> signal(SIGINT, old_sig); >>> } else { /* this will get called on interrupt */ >>> /* you can do what you want - you're back to R-safe code here, so you >>> can either raise an error or return from your function */ >>> /* if you want to trigger regular R interrupt handling, use this: */ >>> R_interrupts_pending = 1; >>> R_CheckUserInterrupt(); >>> /* the above should not return */ >>> } >>> >>> >>> I can capture a SIGINT by redefining signal(SIGINT, myhandler) before calling the lib, but I am somewhat at a loss in terms of what I can do within the hand