egghelp.org community Forum Index
[ egghelp.org home | forum home ]
egghelp.org community
Discussion of eggdrop bots, shell accounts and tcl scripts.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

modules and multi-threading
Goto page 1, 2  Next
 
Post new topic   Reply to topic    egghelp.org community Forum Index -> Modules & Programming
View previous topic :: View next topic  
Author Message
Kappa007
Voice


Joined: 26 Jul 2005
Posts: 38

PostPosted: Wed Mar 01, 2006 8:22 pm    Post subject: modules and multi-threading Reply with quote

Anyone done that already?

Just curious cause since eggdrop itself is not thread-safe, output seems to be a bit cumbersome:
Either you wrap some mutex around the stuff you need or you do some queue which gets polled by some hook (secondly).

Anyone seen/used any other approach?



P.S.: Is there some thread-safe implementation of TCL avail?
Back to top
View user's profile Send private message
demond
Revered One


Joined: 12 Jun 2004
Posts: 3073
Location: San Francisco, CA

PostPosted: Thu Mar 02, 2006 12:41 am    Post subject: Reply with quote

I fail to see a rationale in that

eggdrop is inherently asynchronous, event-driven I/O application and as such, it could hardly benefit from multithreading

maybe a multiserver eggdrop would be better implemented spawning threads (since you have to respond independently, in real time, to events on multiple servers); I thought about starting such project but it would require dedicating a significant amount of my free time (that MT stuff is tricky & hard to get right), too much for a hobby... maybe some day if I'm out of work hehe

of course, I'd applaud you for undertaking an endeavour like this Smile I'm less than impressed with current direction of eggdrop development (javascript/perl scripting etc. - provided they ever complete that, which is highly unlikely, given their pace)
_________________
connection, sharing, dcc problems? click <here>
before asking for scripting help, read <this>
use [code] tag when posting logs, code
Back to top
View user's profile Send private message Visit poster's website
Kappa007
Voice


Joined: 26 Jul 2005
Posts: 38

PostPosted: Thu Mar 02, 2006 11:38 am    Post subject: Reply with quote

It's not about eggdrop benefiting for that kind of multi-threading:

Lets say you want to perform some synchronous I/O in your module or run a lengthy operation.
I assume the bot would be blocked till the call to your module returned.
Easiest way to solve that is to use threads; another way would be to make your module only use async I/O aswell which is not allways possible/desired.
If you use threads then you cannot just call eggdrop's output routines, the module interface functions are just missing locks.

That's my whole issue.
Back to top
View user's profile Send private message
demond
Revered One


Joined: 12 Jun 2004
Posts: 3073
Location: San Francisco, CA

PostPosted: Fri Mar 03, 2006 1:30 am    Post subject: Reply with quote

the only such realistic scenario I can think of is accessing a database, but if it takes *that* long you were forced to handle it in separate thread, there is something wrong with your db design anyway
_________________
connection, sharing, dcc problems? click <here>
before asking for scripting help, read <this>
use [code] tag when posting logs, code
Back to top
View user's profile Send private message Visit poster's website
sKy
Op


Joined: 14 Apr 2005
Posts: 194
Location: Germany

PostPosted: Tue Mar 21, 2006 7:29 am    Post subject: Reply with quote

Ture, eggdrop isn`t mulitthread safe by standard. But it`s possible.

I am using eggdrop 1.6.17 with tcl 8.4.11. The tcl need to be compiled with --enable-threads

When compiling eggdrop you will have to use the tcl version with enabled threads too. Dunno, but i used
./configure --enable-threads

Then install a threading package. I use this here. Works fine.
http://mkextensions.sourceforge.net/ mkThreads 1.2
_________________
socketapi | Code less, create more.
Back to top
View user's profile Send private message
Kappa007
Voice


Joined: 26 Jul 2005
Posts: 38

PostPosted: Thu Mar 23, 2006 8:40 am    Post subject: Reply with quote

However there is an important restriction:
Code:

An important constraint of the Tcl threads implementation is that only the thread that created a Tcl interpreter can use that interpreter. In other words, multiple threads can not access the same Tcl interpreter. (However, a single thread can safely create and use multiple interpreters.)


So a threaded Tcl does not help at all when one wishes to access the Tcl-Iterpreter used by Eggdrop in a multi-threaded module (which is what i wanted to do).

I now push my Tcl commands to a thread-safe queue and do a secondly hook which pops the commands from the queue and executes them in the eggdrop main thread.

Regards,
Kappa
Back to top
View user's profile Send private message
sKy
Op


Joined: 14 Apr 2005
Posts: 194
Location: Germany

PostPosted: Thu Mar 23, 2006 8:55 am    Post subject: Reply with quote

Sorry, I don`t know about modules. :/

I handle this as:
Eggdrop is "globalest level". From there i create a main thread. From the main thread i create all other threads.

By using the tvar command i can:
- show info messages
- show errormessages
- ussing callbacks to the globalest level or other threads

You just write a tvar variable and check and process this on the globalest level. From there you can callback other threads.

This should be a workarround for the code quote you posted. Hope i did get you right and not claim on the wrong three.
_________________
socketapi | Code less, create more.
Back to top
View user's profile Send private message
Kappa007
Voice


Joined: 26 Jul 2005
Posts: 38

PostPosted: Fri Mar 24, 2006 12:32 pm    Post subject: Reply with quote

Ehm no don't think that's a workaround for the quoted statement.
What you say may be perfectly right for Tcl scripts...just got nothing to do with modules or the interpreter itself...
That is unless i got something terribly wrong Cool

You refer to the usage of threads "inside" a tcl interpreter, but the quoted text says that access to a Tcl_Iterp struct is only safe when done from the thread that created it (using Tcl_CreateInterp()).

This means that you cannot use any Tcl_Eval/Set/Get/... functions on the eggdrop tcl interpreter from another thread.
If one would like to do so that would require guarding the interpreter struct with some synchronization primitive (e.g. a mutex).
Back to top
View user's profile Send private message
De Kus
Revered One


Joined: 15 Dec 2002
Posts: 1361
Location: Germany

PostPosted: Fri Mar 24, 2006 2:37 pm    Post subject: Reply with quote

if you want to run a modular task threaded, just run a new process by running either the TCL interpretator or directly the compiled executable. Communication will be done via sockets (redirecting stdin/out). This is the way I use my server status (port scanner) script which might be ready in 1s or take 2min. Of course thats not the solution for modules like stats or seens where the data is stored within a huge memory table. But piping data up to ~1mb should be fast enough.
_________________
De Kus
StarZ|De_Kus, De_Kus or DeKus on IRC
Copyright © 2005-2009 by De Kus - published under The MIT License
Love hurts, love strengthens...
Back to top
View user's profile Send private message MSN Messenger
Kappa007
Voice


Joined: 26 Jul 2005
Posts: 38

PostPosted: Fri Mar 24, 2006 4:05 pm    Post subject: Reply with quote

Yeah, that's also a nice idea to handle that topic.
Didn't even think about that Smile

Ohh just by the way here's the code I currently use to dispatch Tcl commands (just in case anyone cares).

Might be incomplete and missing some #includes, hope no mem-leaks, just a quick copy&paste... Cool

Code:

/* mymodule.c */

static void TclCommandQueueHook()
{   
    CheckTclCommandQueue();   
}

char* mymodule_start(Function* global_funcs)
{
    /* ... */
    InitTclCommandQueue();
    add_hook (HOOK_SECONDLY, (Function)TclCommandQueueHook);
    /* ... */
}


Code:

/* cmdqueue.h */

#ifdef __cplusplus
extern "C"
{
#endif
    int InitTclCommandQueue();
    void DispatchTclCommand( const char* aCommand );
    void CheckTclCommandQueue();

#ifdef __cplusplus
}
#endif


Code:

/* cmdqueue.c */

struct CmdQueueEntry
{
   char* Command;
   struct CmdQueueEntry* Next;
};

struct CmdQueueEntry* CmdQueueStart = NULL;
struct CmdQueueEntry* CmdQueueEnd   = NULL;

/* mutex for the command queue */
pthread_mutex_t*    TclCommandQueueGuard = NULL;

int InitTclCommandQueue()
{
    pthread_mutexattr_t aMutexAttribute;
    pthread_mutexattr_init( &aMutexAttribute );
    pthread_mutexattr_setpshared( &aMutexAttribute, 0 );
    pthread_mutexattr_settype( &aMutexAttribute, PTHREAD_MUTEX_RECURSIVE );

    // initialize mutex
    TclCommandQueueGuard = nmalloc(sizeof( pthread_mutex_t ));
    if (pthread_mutex_init( TclCommandQueueGuard, &aMutexAttribute ) != 0)
    {
        TclCommandQueueGuard = NULL;
        return -1;
    }
    return 0;
}

void DispatchTclCommand( const char* aCommand )
{
   if (TclCommandQueueGuard == NULL) return;      

   pthread_mutex_lock( TclCommandQueueGuard );
   {
      struct CmdQueueEntry* aNewCommand = nmalloc( sizeof( struct CmdQueueEntry ) );
      aNewCommand->Command = nmalloc( strlen( aCommand ) + 1 );
      strncpy( aNewCommand->Command, aCommand, strlen(aCommand) );
      aNewCommand->Command[strlen( aCommand )] = '\0';
      aNewCommand->Next = NULL;

      // no end set yet?
      if (CmdQueueEnd == NULL)
      {
         // start from the beginning
         struct CmdQueueEntry* Next = CmdQueueStart;
         if (Next != NULL)
         {
            while (Next->Next != NULL)
            {
               Next = Next->Next;
            }
            CmdQueueEnd = Next;
         }
         // no start yet?
         else
         {
            CmdQueueStart = aNewCommand;
            CmdQueueEnd = aNewCommand;
         }
      }
      else
      {
         CmdQueueEnd->Next = aNewCommand;
         CmdQueueEnd = aNewCommand;
      }
   }
   pthread_mutex_unlock( TclCommandQueueGuard );
}   

void CheckTclCommandQueue()
{
   if (TclCommandQueueGuard == NULL) return;      

   pthread_mutex_lock( TclCommandQueueGuard );
   {
      while (CmdQueueStart != NULL)
      {
         if (CmdQueueStart->Command != NULL)
         {
            Tcl_EvalEx( interp, CmdQueueStart->Command, -1, TCL_EVAL_GLOBAL );
            nfree( CmdQueueStart->Command );
         }         
         struct CmdQueueEntry* Next = CmdQueueStart->Next;
         nfree( CmdQueueStart );
         CmdQueueStart = Next;
      }
      CmdQueueEnd = CmdQueueStart;
   }
   pthread_mutex_unlock( TclCommandQueueGuard );
}
Back to top
View user's profile Send private message
demond
Revered One


Joined: 12 Jun 2004
Posts: 3073
Location: San Francisco, CA

PostPosted: Tue Mar 28, 2006 1:47 am    Post subject: Reply with quote

Kappa007 wrote:

Ohh just by the way here's the code I currently use to dispatch Tcl commands (just in case anyone cares).


I'd care if your efforts serve a purpose other than exercising your MT skills - that is, an eggdrop purpose (and you are able to demonstrate how eggdrop benefits from that)
_________________
connection, sharing, dcc problems? click <here>
before asking for scripting help, read <this>
use [code] tag when posting logs, code
Back to top
View user's profile Send private message Visit poster's website
Kappa007
Voice


Joined: 26 Jul 2005
Posts: 38

PostPosted: Fri Mar 31, 2006 6:08 am    Post subject: Reply with quote

Well benefits are: you can use (foreign) code which uses blocking calls in your modules w/o having to worry about your eggdrop beeing stalled.
And that's enough for me Smile

And if that does not count for you then it's just about the possibility to use them at all Razz
Back to top
View user's profile Send private message
De Kus
Revered One


Joined: 15 Dec 2002
Posts: 1361
Location: Germany

PostPosted: Fri Mar 31, 2006 6:44 am    Post subject: Reply with quote

Kappa007 wrote:
Well benefits are: you can use (foreign) code which uses blocking calls in your modules w/o having to worry about your eggdrop beeing stalled.
And that's enough for me Smile

Did you read my post? Its absoludly possible to run asyncron tasks. Btw. the reason eggdrop is so popular is, because its single threaded. That way shells can restrict eggdrop shells to 1 bg process. For further background tasks possible. Furthermore 1 bg process eggdrop = 1 IRC connection. For hosting on a general shell account with multiple back processes and connections allowed it might be usefull, but that wouldnt be all. Eggdrop is and will always keep single threaded and single server for these reasons. You can however still fork into a forground thread to execute async calls as mentioned above by me.
_________________
De Kus
StarZ|De_Kus, De_Kus or DeKus on IRC
Copyright © 2005-2009 by De Kus - published under The MIT License
Love hurts, love strengthens...
Back to top
View user's profile Send private message MSN Messenger
Kappa007
Voice


Joined: 26 Jul 2005
Posts: 38

PostPosted: Fri Mar 31, 2006 2:32 pm    Post subject: Reply with quote

Ehhh yes I read it, i even replied in case you didn't notice...

Kappa007 wrote:

Yeah, that's also a nice idea to handle that topic.
Didn't even think about that Smile
Back to top
View user's profile Send private message
demond
Revered One


Joined: 12 Jun 2004
Posts: 3073
Location: San Francisco, CA

PostPosted: Sat Apr 01, 2006 3:31 am    Post subject: Reply with quote

Kappa007 wrote:
Well benefits are: you can use (foreign) code which uses blocking calls in your modules w/o having to worry about your eggdrop beeing stalled.
And that's enough for me Smile

And if that does not count for you then it's just about the possibility to use them at all Razz


well, you're still on the proof-of-concept stage

I'd applaud if you roll out, say, a non-blocking mysql module

and I'd admire you for producing multi-server MT eggdrop
_________________
connection, sharing, dcc problems? click <here>
before asking for scripting help, read <this>
use [code] tag when posting logs, code
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    egghelp.org community Forum Index -> Modules & Programming All times are GMT - 4 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Forum hosting provided by Reverse.net

Powered by phpBB © 2001, 2005 phpBB Group
subGreen style by ktauber