[sane-devel] Are sane_cancel implementations safe to be called from signal handler?

Johannes Meixner jsmeix at suse.de
Thu Aug 26 10:35:23 UTC 2010


Hello,

we (i.e. openSUSE/Novell) got this bug report:

https://bugzilla.novell.com/show_bug.cgi?id=631294

In short:

It seems the sane_cancel implementations in particular backends
are not safe to be called from signal handler which may lead
to arbitrary issues.
E.g. the frontend "scanimage" cannot be killed with SIGKILL
while it is waiting in futex(...) in certain circumstances.

Details:

The SANE1 API documentation regarding sane_cancel reads that
it is safe to call this function asynchronously
(e.g., from within a signal handler).

Calling sane_cancel from within a signal handler is what
the frontend "scanimage" does in its "sighandler" function
which is set for SIGHUP, SIGINT, SIGPIPE, and SIGTERM.

Therefore according to my current understanding
it seems each individual backend would have to be
checked whether or not its individual implementation
of the sane_cancel function is really safe to be called
from within a signal handler.

Just two examples:

The sane_cancel implementation in backend/epson2.c
looks safe to be called from within a signal handler:
---------------------------------------------------------------------
/* void sane_cancel(SANE_Handle handle)
  * Set the cancel flag to true. The next time the backend requests
  * data from the scanner the CAN message will be sent.
  */
void
sane_cancel(SANE_Handle handle)
{
   Epson_Scanner *s = (Epson_Scanner *) handle;
   s->canceling = SANE_TRUE;
}
---------------------------------------------------------------------

In contrast the sane_cancel implementation in backend/plustek.c
does not look safe to be called from within a signal handler:
---------------------------------------------------------------------
/** cancel the scanning process
  */
void
sane_cancel( SANE_Handle handle )
{
   Plustek_Scanner *s = (Plustek_Scanner *)handle;
   DBG( _DBG_SANE_INIT, "sane_cancel\n" );
   if (s->scanning || s->calibrating)
     do_cancel( s, SANE_FALSE );
}
---------------------------------------------------------------------
because "do_cancel" is a bigger function which does
all what is needed to stop the current scan process.


Kind Regards
Johannes Meixner
-- 
SUSE LINUX Products GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany
AG Nuernberg, HRB 16746, GF: Markus Rex



More information about the sane-devel mailing list