#hurd, freenode, 2010-05-19
<cfhammar> ugh, mig server stubs generated from *_reply.defs don't call the server functions when the reply is an error, since the message size is too small...
<cfhammar> term seems to get around it by turning of type checking
<cfhammar> s/of/off
<cfhammar> but streamio doesn't
<cfhammar> luckily the only other program that makes use of a *_reply.defs is crash, and crash_reply.defs' routines only return an error code so it isn't affected
<slpz> cfhammar: could you point me to a stub with that problem?
<cfhammar> slpz: trans/device_replyServer.c:_Xdevice_open_reply (in build dir)
<slpz> cfhammar: So, if I understand it correctly, the problem is that GNU Mach generated stub doesn't properly set the size of the message if there's an error in the function, thus the type checking in user generated stub discards the reply
<cfhammar> slpz: the size is correct, error messages contain just a return value
<cfhammar> slpz: it is the type checking that is at fault imho
<slpz> cfhammar: even when a server wants to return an error, the size of the message should be the same as the reply structure previously defined
<slpz> cfhammar: on the other hand, I can't understand why streamio is using device_open_request (async RPC) instead of device_open (sync RPC)...
<cfhammar> slpz: the server does not always know the proper size, e.g. when it doesn't understand the message
<slpz> cfhammar: what do you mean by "doesn't understand the message"?
<cfhammar> slpz: if it doesn't implement that interface or is the wrong type, etc.
<cfhammar> slpz: in that case the mig stub needs to send out a generic error reply
<cfhammar> slpz: i don't know why streamio uses it either
<slpz> cfhammar: OK, now I see your point. If the server answers with a generic error code (as MIG_*), device_open_reply will not be called, and device_open_request doesn't get an error.
<slpz> cfhammar: good catch :-)
<cfhammar> slpz: all errors are handled the same way, MIG_* is just an example of why it does so
<slpz> cfhammar: on an unrealted note, I think we should get rid of all asynchronous messages sent from the user to the kernel, since they aren't asynchronous except for sending the reply to a different port (the process is really done by the thread calling mach_msg)
<cfhammar> slpz: i'm not not all that familiar with the low-level parts of message passing so i can't really comment
<slpz> cfhammar: in that point I disagree. If the server function can understand the message (so there isn't a MIG_* error), it can send a reply message with the proper size
<cfhammar> slpz: it could, but what is the advantage if we still need to handle generic errors?
<cfhammar> slpz: "sending the reply to a different port", different from what?
<slpz> cfhammar: to differentiate between message marshalling errors and errors generated by the called function
<slpz> cfhammar: in a synchronous RPC, the same call to mach_msg will send the request and receive the reply by providing a mig generated reply port
<slpz> cfhammar: but in an asynchronous, the reply is received by a port previously generated by the function requesting the message
<cfhammar> slpz: ah, that's a clever optimization
<slpz> cfhammar: if the "asynchronous" message is sent to the kernel, the thread calling for mach_msg will execute the server's function, but the reply will be sent to one of these previously generated ports
<slpz> cfhammar: actually you have a synchronous operation replying to a different port. That doesn't make much sense to me :-)
<antrik> slpz: note that most kernel functions can be implemented by userspace servers, in which case they could be really async...
<cfhammar> slpz: not sure how differentiating mig errors from server errors is useful...
<slpz> antrik: define "most kernel functions" ;-)
<cfhammar> slpz: if nothing else kernel rpcs can be proxied, e.g. rpctrace
<slpz> cfhammar: well, think of device_open_request. If the result is not a mig error, you can still device_open_reply an expect it to properly process the return code from the message
<cfhammar> slpz: it should be able to handle all kinds of errors anyway, the result should be the same as with syncronous rpcs
<slpz> cfhammar: yes, you're right. User generated stub should be able to fill the reply with the error code and call to the reply function.
<slpz> cfhammar: Then someone needs to introduce some changes in MiG's magic...
<cfhammar> slpz: yes, a flag to generate reply side of an interface would be ideal
<cfhammar> slpz: then we could toss out *_reply.defs altogether
<slpz> cfhammar: well, that's a different change from what I was thinking
<cfhammar> slpz: how would you change it?
<slpz> cfhammar: just generating stubs which, in case of error, will properly call to the reply function with the error code in its arguments
<cfhammar> slpz: ah yes, i considered that as well, but i don't think mig can actually distinguish the error code from any other int argument
<cfhammar> slpz: i should double check it though
<slpz> cfhammar: I tag can be used to point to argument of this nature
<slpz> cfhammar: s/I/A/
<cfhammar> slpz: oh, it already is tagged with retcode, intresting
<slpz> cfhammar: OMG, I'm thinking like MiG! ;-P
<cfhammar> slpz: is that a good or bad ;
<cfhammar> slpz: ;-)
<slpz> cfhammar: I don't know, but it's somewhat scary ;-)
<cfhammar> slpz: apparently retcode is only there for comatibility, mig just ignores it...