thread safety.

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

thread safety.

George Neill
Hi All,

Thanks for awesome Lua language, this is my first post to the mailing list!

I did a quick double check for some known non-reentrant functions and
I found a handful of potential MT issues in loslib.c

os_execute calls system() not MT safe.
os_date calls either gmtime() or localtime() both are not MT safe.

... possibly others?

I'd like to fix those which can be fixed and provide a patch, would it
be preferable to enable a macro named something like
LUA_USE_REENTRANT?

TIA,
George
Reply | Threaded
Open this post in threaded view
|

Re: thread safety.

Asko Kauppi

The re-entrant gmtime_r() and localtime_r() are not ANSI C, I believe.  
You can provide a patch but inclusion of non-ANSI C features has  
seemed to be a 'no'. Maybe this will change, eventually.

"The asctime_r(), ctime_r(), gmtime_r(), and localtime_r() functions  
are expected to conform to ISO/IEC 9945-1:1996 (``POSIX.1'')"

Can you post a case where using such functions really presents a  
hazard, in a multithreaded application?

Why do you think 'system' is a problem?  Maybe it's been on the  
warning list because when you launch external programs, there's no  
guarantee how multithread unfriendly they could be? I find no problem  
with 'system()' itself.

-asko



George Neill kirjoitti 12.6.2009 kello 3:11:

> Hi All,
>
> Thanks for awesome Lua language, this is my first post to the  
> mailing list!
>
> I did a quick double check for some known non-reentrant functions and
> I found a handful of potential MT issues in loslib.c
>
> os_execute calls system() not MT safe.
> os_date calls either gmtime() or localtime() both are not MT safe.
>
> ... possibly others?
>
> I'd like to fix those which can be fixed and provide a patch, would it
> be preferable to enable a macro named something like
> LUA_USE_REENTRANT?
>
> TIA,
> George

Reply | Threaded
Open this post in threaded view
|

Re: thread safety.

George Neill
Asko,

On Thu, Jun 11, 2009 at 11:54 PM, Asko Kauppi<[hidden email]> wrote:
>
> The re-entrant gmtime_r() and localtime_r() are not ANSI C, I believe. You
> can provide a patch but inclusion of non-ANSI C features has seemed to be a
> 'no'. Maybe this will change, eventually.
>
> "The asctime_r(), ctime_r(), gmtime_r(), and localtime_r() functions are
> expected to conform to ISO/IEC 9945-1:1996 (``POSIX.1'')"

right, indeed gmtime_r/localtime_r would fall under LUA_USE_POSIX

from solaris localtime manpage,

     The asctime(), ctime(), gmtime(), and localtime()  functions
     are  safe  to  use  in multithread applications because they
     employ  thread-specific  data.   However,   their   use   is
     discouraged  because  standards  do  not  require them to be

from linux (ubuntu) localtime manpage,

       The four functions asctime(), ctime(), gmtime() and localtime()  return
       a  pointer  to  static data and hence are not thread-safe.  Thread-safe
       versions asctime_r(), ctime_r(), gmtime_r() and localtime_r() are spec‐
       ified by SUSv2, and available since libc 5.2.5.

so gmtime/localtime are not required to be thread-safe by the standard
... but some vendors have made them thread-safe.

> Can you post a case where using such functions really presents a hazard, in
> a multithreaded application?

of course, I will try to put together an example that breaks for you.
The idea would be to have two or more threads with their own lua
state; and at the same time, have one writing to the static data the
other reading from it.

> Why do you think 'system' is a problem?  Maybe it's been on the warning list
> because when you launch external programs, there's no guarantee how
> multithread unfriendly they could be? I find no problem with 'system()'
> itself.

from solaris system(3c) man page,

     The system() function manipulates the  signal  handlers  for
     SIGINT,  SIGQUIT,  and  SIGCHLD. It is therefore not safe to
     call system() in a multithreaded process, since  some  other
     thread  that  manipulates these signal handlers and a thread
     that concurrently calls system()  can  interfere  with  each
     other  in  a destructive manner.  If, however, no such other
     thread is active, system() can safely be called concurrently
     from  multiple  threads. See popen(3C) for an alternative to
     system() that is thread-safe.

they suggest,

       int my_system(const char *cmd)
       {
              FILE *p;

              if ((p = popen(cmd, "w")) == NULL)
                      return (-1);
              return (pclose(p));
       }

as a system() alternative.


Thanks,
George.
Reply | Threaded
Open this post in threaded view
|

Re: thread safety.

Luiz Henrique de Figueiredo
> right, indeed gmtime_r/localtime_r would fall under LUA_USE_POSIX

If those have the same signature as the ANSI functions, you can simply
add a section with #defines at the end of luaconf.h
Reply | Threaded
Open this post in threaded view
|

Re: thread safety.

George Neill
Luiz,

On Fri, Jun 12, 2009 at 9:04 AM, Luiz Henrique de
Figueiredo<[hidden email]> wrote:
>> right, indeed gmtime_r/localtime_r would fall under LUA_USE_POSIX
>
> If those have the same signature as the ANSI functions, you can simply
> add a section with #defines at the end of luaconf.h

They are not the same, each add an additional parameter.

Later,
George
Reply | Threaded
Open this post in threaded view
|

Re: thread safety.

George Neill
In reply to this post by Asko Kauppi
Asko,

On Thu, Jun 11, 2009 at 11:54 PM, Asko Kauppi<[hidden email]> wrote:

>
> The re-entrant gmtime_r() and localtime_r() are not ANSI C, I believe. You
> can provide a patch but inclusion of non-ANSI C features has seemed to be a
> 'no'. Maybe this will change, eventually.
>
> "The asctime_r(), ctime_r(), gmtime_r(), and localtime_r() functions are
> expected to conform to ISO/IEC 9945-1:1996 (``POSIX.1'')"
>
> Can you post a case where using such functions really presents a hazard, in
> a multithreaded application?

Sorry for the delay,

gneill@blackfoot:~/lua-dev$ cat localtime.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

void *onef(void *arg)
{
  time_t t = (time_t)0;
  struct tm * stm;

  stm = localtime(&t);

  fprintf(stdout, "one localtime [%p]\n", stm);

  return (void*)NULL;
}

void *twof(void *arg)
{
  time_t t = (time_t)0;
  struct tm * stm;

  stm = localtime(&t);

  fprintf(stdout, "two localtime [%p]\n", stm);

  return (void*)NULL;
}

void *threef(void *arg)
{
  time_t t = (time_t)0;
  struct tm * stm;

  stm = gmtime(&t);

  fprintf(stdout, "three gmtime [%p]\n", stm);

  return (void*)NULL;
}

int main(int argc, char *argv[])
{
  pthread_t one;
  pthread_t two;
  pthread_t three;

  pthread_create(&one, NULL, onef, NULL);
  pthread_create(&two, NULL, twof, NULL);
  pthread_create(&three, NULL, threef, NULL);

  pthread_join(one, NULL);
  pthread_join(two, NULL);
  pthread_join(three, NULL);

  return 0;
}

gneill@blackfoot:~/lua-dev$ !gcc
gcc -lpthread localtime.c

gneill@blackfoot:~/lua-dev$ ./a.out
one localtime [0xb805b380]
two localtime [0xb805b380]
three gmtime [0xb805b380]

The example only proves the three threads have been given back the
same memory address.  But I think it's fair to say that it is not a
good idea to use in a threaded application (without some locking).

HTH,
George