Pardon my ignorance, but here it goes.
I am at the moment writing a general LPC-type server in Pike, mainly for my own amusement, and have run into a problem. First let me give a rundown. I'm sorry if it's long-winded, I like to put all the information out so I don't confuse with my incorrect jargon and don't miss anything important.
The server sets up all the constants (located in inherited file) binds to a port and listens. Once a connection attempt is found it sends it to a socket class. The socket class then attempts to clone the player object, (compiles the program pointed to by a #define) and calls the logon() in the compiled object.
The server itself, handling connections, cloning of objects, and basically everything works just fine. An LPC-alike clone mud can be built. I have a constant:
add_constant("this_user", function_object(backtrace()[-2]->fun));
Which works wonderfully enough while it is inside the player program.
My problem:
I have a "bin" system for the player commands. It matches the input, searches for an object compiled under that name (i.e. /lib/cmds/who.p when they type who), compiling if not, then calls the do_cmd() function within it. If the this_user() constant is called from within the called command function it returns 0. A backtrace returns an array of 3 Zeroes. The "function_object(backtrace()[-2]->fun)" works fine within it, only the constant has a problem.
Currently I am circumventing this by using a #define for the backtrace, but it is rather annoying and unsightly. I was wondering if there was some other way of doing this, or if I was doing something hideously wrong. At least some way of hitting the backtrace info from within such an above example, I can always set checking to make sure it's hitting the right backtrace entry, just need the info first *grin*.
Kaylus
p.s. Sorry if this was somewhat lengthy, pointless, blather that is hard to read. It's 2am and i've been trying to figure it out for quite some time. Please ignore slight errors in the message!
add_constant("this_user", function_object(backtrace()[-2]->fun));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
That will be relative to where you do add_constant, is that really what you want?
You probably want to do something like,
| User calculate_current_user() | { | // really calculate the user from for instance the backtrace | return ...; | } | | ... | add_constant("this_user",calculate_current_user);
/ Mirar
Previous text:
2003-08-29 08:18: Subject: Problems with Backtrace
Pardon my ignorance, but here it goes.
I am at the moment writing a general LPC-type server in Pike, mainly for my own amusement, and have run into a problem. First let me give a rundown. I'm sorry if it's long-winded, I like to put all the information out so I don't confuse with my incorrect jargon and don't miss anything important.
The server sets up all the constants (located in inherited file) binds to a port and listens. Once a connection attempt is found it sends it to a socket class. The socket class then attempts to clone the player object, (compiles the program pointed to by a #define) and calls the logon() in the compiled object.
The server itself, handling connections, cloning of objects, and basically everything works just fine. An LPC-alike clone mud can be built. I have a constant:
add_constant("this_user", function_object(backtrace()[-2]->fun));
Which works wonderfully enough while it is inside the player program.
My problem:
I have a "bin" system for the player commands. It matches the input, searches for an object compiled under that name (i.e. /lib/cmds/who.p when they type who), compiling if not, then calls the do_cmd() function within it. If the this_user() constant is called from within the called command function it returns 0. A backtrace returns an array of 3 Zeroes. The "function_object(backtrace()[-2]->fun)" works fine within it, only the constant has a problem.
Currently I am circumventing this by using a #define for the backtrace, but it is rather annoying and unsightly. I was wondering if there was some other way of doing this, or if I was doing something hideously wrong. At least some way of hitting the backtrace info from within such an above example, I can always set checking to make sure it's hitting the right backtrace entry, just need the info first *grin*.
Kaylus
p.s. Sorry if this was somewhat lengthy, pointless, blather that is hard to read. It's 2am and i've been trying to figure it out for quite some time. Please ignore slight errors in the message!
/ kaylus
Oddly enough, I was ready to shoot back with a dry, semi-sarcastic reply on how i'd already tried such, when I went and decided to try it and it worked. Bah on you! Maybe it really was too early in the morning for my mind to function. I thought it a myth.
Honestly, I still don't understand why that would have been causing it to return a 0 from that one function yet work fine everywhere else. Thanks, though, for the (if even slap-you-in-the-face, because-it's-so-simple) help. I appreciate it greatly.
Kaylus
/ kaylus
Previous text:
2003-08-29 08:37: Subject: Problems with Backtrace
add_constant("this_user", function_object(backtrace()[-2]->fun));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
That will be relative to where you do add_constant, is that really what you want?
You probably want to do something like,
| User calculate_current_user() | { | // really calculate the user from for instance the backtrace | return ...; | } | | ... | add_constant("this_user",calculate_current_user);
/ Mirar
I'm not sure why you got 0 sometimes either. :) But, well, now we don't have to figure that out :)
/ Mirar
Previous text:
2003-08-29 13:26: Subject: Problems with Backtrace
Oddly enough, I was ready to shoot back with a dry, semi-sarcastic reply on how i'd already tried such, when I went and decided to try it and it worked. Bah on you! Maybe it really was too early in the morning for my mind to function. I thought it a myth.
Honestly, I still don't understand why that would have been causing it to return a 0 from that one function yet work fine everywhere else. Thanks, though, for the (if even slap-you-in-the-face, because-it's-so-simple) help. I appreciate it greatly.
Kaylus
/ kaylus
Well, I guess we don't, then! Changed the -2 to a 4, after realizing my user object stays in the same location (so far) in reletion to the start of the backtrace array and now it works wonderfully.
Now is time to go back and wreak more Havoc upon my poor server, with a working this_user(), muahaha. Thanks again.
Kaylus
/ kaylus
Previous text:
2003-08-29 13:33: Subject: Problems with Backtrace
I'm not sure why you got 0 sometimes either. :) But, well, now we don't have to figure that out :)
/ Mirar
You might want to do some more sanity checking on the function, in case it was called from for instance a call_out. (Although you might want to rewrite call_out so it keeps the user object.)
I bet this crashes now, for instance: call_out(this_user,0);
I suggest putting, in the (base) user class: constant is_user_object=1;
and a sanity check in the this_user function, like this,
array b=backtrace(); if (sizeof(b)>4 && ...b[4]...->is_user_object) return it; foreach (b;;array v) if (...v...->is_user_object) return it; return 0;
/ Mirar
Previous text:
2003-08-29 13:43: Subject: Problems with Backtrace
Well, I guess we don't, then! Changed the -2 to a 4, after realizing my user object stays in the same location (so far) in reletion to the start of the backtrace array and now it works wonderfully.
Now is time to go back and wreak more Havoc upon my poor server, with a working this_user(), muahaha. Thanks again.
Kaylus
/ kaylus
On Fri, Aug 29, 2003 at 08:25:02AM -0400, Mirar @ Pike developers forum wrote:
array b=backtrace(); if (sizeof(b)>4 && ...b[4]...->is_user_object) return it; foreach (b;;array v) if (...v...->is_user_object) return it;
the thing i don't understand is, why use a backtrace to find the user object?
is there no simpler way to do this?
greetings, martin.
I suppose you could store something thread-locally, but wouldn't it be about as complicated?
/ Mirar
Previous text:
2003-08-29 14:52: Subject: Re: Problems with Backtrace
On Fri, Aug 29, 2003 at 08:25:02AM -0400, Mirar @ Pike developers forum wrote:
array b=backtrace(); if (sizeof(b)>4 && ...b[4]...->is_user_object) return it; foreach (b;;array v) if (...v...->is_user_object) return it;
the thing i don't understand is, why use a backtrace to find the user object?
is there no simpler way to do this?
greetings, martin.
/ Brevbäraren
I bet this crashes now, for instance: call_out(this_user,0);
You are exactly right.
I suggest putting, in the (base) user class: constant is_user_object=1;
The only problem I have with that, is that the server itself doesn't control anything about the user class or attempt to define anything about it. Plus, the socket class just links the socket to an object and allows for the socket to be relinked to any object on the go.
I'd rather take care of it myself, to keep that extra bit out of anyone's face (like anyone will actually use it, heh)
and a sanity check in the this_user function, like this,
array b=backtrace(); if (sizeof(b)>4 && ...b[4]...->is_user_object) return it; foreach (b;;array v) if (...v...->is_user_object) return it; return 0;
What I went ahead and did was basically what you just wrote here, with the exception that I had it call a function that to checks to see if an object is referring to an interactive (socket-linked) obj.
Martin:
the thing i don't understand is, why use a backtrace to find the user object? is there no simpler way to do this?
Not really after the compat for previous object was removed from Pike. As I said, my server is written with LPC in mind, split server and mudlib. I don't want the two (server + lib) to be conjoined by kludge code, and the only other way, besides previously mentioned, I can see would be passing the pointer of the users current object to each function they call.
How other way would this work and be able to distinguish the user that is calling a function that would be less complex?
Kaylus
/ kaylus
Previous text:
2003-08-29 15:20: Subject: Re: Problems with Backtrace
I suppose you could store something thread-locally, but wouldn't it be about as complicated?
/ Mirar
pike-devel@lists.lysator.liu.se