Hi people: We are developing SqueakDBX, an openDBX (http://www.linuxnetworks.de/doc/index.php/OpenDBX) wrapper, that let us communicate with major relational databases through a common API. OpenDBX is a C library. SqueakDBX uses FFI to call those functions. Now, I am getting an error with a select() invocation in that code.
This is a piece of the openDBX function with the problem: static int pgsql_odbx_result( odbx_t* handle, odbx_result_t** result, struct timeval* timeout, unsigned long chunk ) { struct pgconn* conn = (struct pgconn* ) handle->aux; if( timeout != NULL ) { fprintf( stdout, "timeval tv_sec value: %d\n", timeout->tv_sec ); fprintf( stdout, "timeval tv_usec value: %d\n", timeout->tv_usec ); } else { puts("El timeval is null"); } ...... #ifdef HAVE_SELECT if( timeout != NULL && PQisBusy( (PGconn*) handle->generic ) == 1 ) { int fd; fd_set fds; if( ( fd = PQsocket( (PGconn*) handle->generic ) ) == -1 ) { conn->errtype = -1; return -ODBX_ERR_BACKEND; } FD_ZERO( &fds ); FD_SET( fd, &fds ); switch( select( fd + 1, &fds, NULL, NULL, timeout ) ) { case -1: printf( "Error with select function: %s\n", strerror( errno ) ); return -ODBX_ERR_RESULT; case 0: return ODBX_RES_TIMEOUT; /* timeout while waiting for a result */ } } #endif Now, I have a problem with select() invocation. This function returns -1. And the printf of the errno (where select() stores the errors), says: "Error with select function: Interrupted system call" which means I am getting a EINTR error. If you see console, you can see something like this: timeval tv_usec value: 0 timeval tv_sec value: 3 timeval tv_usec value: 0 timeval tv_sec value: 2 timeval tv_usec value: 996000 timeval tv_sec value: 3 timeval tv_usec value: 0 Error with select function: Interrupted system call I asked Norbert (openDBX author) and he tell me exactly this: "An interrupted system call is something very normal because signals can be sent at every time to the application, either by the system or by the user. I guess, in the Squeak code there is some signal handler installed, which does something if one of the defined signals arrive. What I will do is to hide the consequences (returning an error) by looking at the error value and reenter the select call if the system call is interrupted." All I know is squeakVM is written it SLANG and then that's transformed to C. So, squeakVM runs in C. So, there is where it can be a signal handler ? Is there some way to change that from squeak (image) ? I am still newbie so I really need help with this. Thanks for the help in advance. Mariano |
On Sun, Jan 25, 2009 at 08:50:35PM -0200, Mariano Martinez Peck wrote:
> > Now, I have a problem with select() invocation. This function returns -1. > And the printf of the errno (where select() stores the errors), says: "Error > with select function: Interrupted system call" which means I am getting a > EINTR error. If you see console, you can see something like this: > > timeval tv_usec value: 0 > timeval tv_sec value: 3 > timeval tv_usec value: 0 > timeval tv_sec value: 2 > timeval tv_usec value: 996000 > timeval tv_sec value: 3 > timeval tv_usec value: 0 > Error with select function: Interrupted system call > > > I asked Norbert (openDBX author) and he tell me exactly this: > > "An interrupted system call is something very normal because signals can be > sent > at every time to the application, either by the system or by the user. I > guess, in the Squeak code there is some signal handler installed, which does > something if one of the defined signals arrive. > > What I will do is to hide the consequences (returning an error) by looking > at > the error value and reenter the select call if the system call is > interrupted." Norbert is correct, and his solution of reentering the system call sounds like the right thing to do. > All I know is squeakVM is written it SLANG and then that's transformed to C. > So, squeakVM runs in C. So, there is where it can be a signal handler ? Is > there some way to change that from squeak (image) ? Any interrupt handler will service interrupts for the entire VM, so this is not something that you would want to set up for a specific plugin. If one plugin sets a signal handler, it affects all other plugins as well as the VM itself. It is actually quite easy to experiment with setting signal handlers if you are using a Unix VM and if you have OSProcess installed. For example, if you want to handle the SIGQUIT signal, you can evualate the expression 'OSProcess accessor forwardSigQuit' to get a Smalltalk semaphore that will be signalled each time the operating system sends a SIGQUIT (signal number 3) to the VM. You can have a Squeak process that waits on the semaphore and does whatever you like. To be clear however, Norbert's explanation is correct regardless of how the VM chooses to handle a signal. When a system call such as select is interrupted, the application (your plugin) needs to check for this and retry the system call. HTH, Dave |
Indeed. We did some work with RS485 support for the Serial plugin... EINTRs
happen all the time... recommended to retry (see Linux documentation around the web as to why). Obviously, in a plugin, the retry can happen quite quickly. Not sure how using FFI might respond. Regards, Gary. ----- Original Message ----- From: "David T. Lewis" <[hidden email]> To: "The general-purpose Squeak developers list" <[hidden email]> Sent: Monday, January 26, 2009 1:50 AM Subject: Re: [squeak-dev] Help needed with select() socket function and signalhandlers in squeakVM > On Sun, Jan 25, 2009 at 08:50:35PM -0200, Mariano Martinez Peck wrote: >> >> Now, I have a problem with select() invocation. This function returns -1. >> And the printf of the errno (where select() stores the errors), says: >> "Error >> with select function: Interrupted system call" which means I am getting a >> EINTR error. If you see console, you can see something like this: >> >> timeval tv_usec value: 0 >> timeval tv_sec value: 3 >> timeval tv_usec value: 0 >> timeval tv_sec value: 2 >> timeval tv_usec value: 996000 >> timeval tv_sec value: 3 >> timeval tv_usec value: 0 >> Error with select function: Interrupted system call >> >> >> I asked Norbert (openDBX author) and he tell me exactly this: >> >> "An interrupted system call is something very normal because signals can >> be >> sent >> at every time to the application, either by the system or by the user. I >> guess, in the Squeak code there is some signal handler installed, which >> does >> something if one of the defined signals arrive. >> >> What I will do is to hide the consequences (returning an error) by >> looking >> at >> the error value and reenter the select call if the system call is >> interrupted." > > Norbert is correct, and his solution of reentering the system call sounds > like the right thing to do. > >> All I know is squeakVM is written it SLANG and then that's transformed to >> C. >> So, squeakVM runs in C. So, there is where it can be a signal handler ? >> Is >> there some way to change that from squeak (image) ? > > Any interrupt handler will service interrupts for the entire VM, so this > is > not something that you would want to set up for a specific plugin. If one > plugin sets a signal handler, it affects all other plugins as well as the > VM itself. > > It is actually quite easy to experiment with setting signal handlers if > you are using a Unix VM and if you have OSProcess installed. For example, > if you want to handle the SIGQUIT signal, you can evualate the expression > 'OSProcess accessor forwardSigQuit' to get a Smalltalk semaphore that will > be > signalled each time the operating system sends a SIGQUIT (signal number 3) > to the VM. You can have a Squeak process that waits on the semaphore and > does > whatever you like. > > To be clear however, Norbert's explanation is correct regardless of how > the VM chooses to handle a signal. When a system call such as select is > interrupted, the application (your plugin) needs to check for this and > retry the system call. > > HTH, > > Dave > > |
David T. Lewis: Very useful your explanation.
Gary: thanks too. If fact, I did what you tell we. The problem was that the select() invocation was inside a specific function of OpenDBX. From SqueakDBX the only thing I can do is to call again that function, but this is very different that only call select() function again. So, what I change openDBX code from this: if( ( fd = PQsocket( (PGconn*) handle->generic ) ) == -1 ) { conn->errtype = -1; return -ODBX_ERR_BACKEND; } FD_ZERO( &fds ); FD_SET( fd, &fds ); switch( select( fd + 1, &fds, NULL, NULL, timeout ) ) to do { if( ( fd = PQsocket( (PGconn*) handle->generic ) ) == -1 ) { conn->errtype = -1; return -ODBX_ERR_BACKEND; } FD_ZERO( &fds ); FD_SET( fd, &fds ); rv = select( fd + 1, &fds, NULL, NULL, timeout ); } while ((rv == -1) && (errno == EINTR)); switch( rv ) And now It works perfect. It was difficult to reproduce because openDBX tests where ok, but squeakDBX ones not. This is because of SqueakVM as you explain me. So, I am waiting openDBX author feedback about my code, but at least it work!!! Thanks for the help again. Mariano On Mon, Jan 26, 2009 at 8:11 PM, Gary Chambers <[hidden email]> wrote: Indeed. We did some work with RS485 support for the Serial plugin... EINTRs happen all the time... recommended to retry (see Linux documentation around the web as to why). Obviously, in a plugin, the retry can happen quite quickly. Not sure how using FFI might respond. |
On Wed, Jan 28, 2009 at 12:51:04AM -0200, Mariano Martinez Peck wrote:
> > So, what I change openDBX code from this: > > if( ( fd = PQsocket( (PGconn*) handle->generic ) ) == -1 ) > { > conn->errtype = -1; > return -ODBX_ERR_BACKEND; > } > > FD_ZERO( &fds ); > FD_SET( fd, &fds ); > > switch( select( fd + 1, &fds, NULL, NULL, timeout ) ) > > > > to > > > do { > > if( ( fd = PQsocket( (PGconn*) handle->generic ) ) == -1 ) > { > conn->errtype = -1; > return -ODBX_ERR_BACKEND; > } > > FD_ZERO( &fds ); > FD_SET( fd, &fds ); > > rv = select( fd + 1, &fds, NULL, NULL, timeout ); > > } while ((rv == -1) && (errno == EINTR)); > > switch( rv ) > > > And now It works perfect. It was difficult to reproduce because openDBX > tests where ok, but squeakDBX ones not. This is because of SqueakVM as you > explain me. Your change looks right to me. Dave |
David: Thanks for your help and time!
Norbert (openDBX author) just just tell me this is ok, but checking with PQisBusy() again shouldn't be necessary. So, it was simplified and commited to svn. Actually now, it is like this: #ifdef HAVE_SELECTI test it and works like a charm. thanks again. Mariano On Wed, Jan 28, 2009 at 7:19 PM, David T. Lewis <[hidden email]> wrote:
|
Free forum by Nabble | Edit this page |