Thanks for the info.
I just made a test program to converse with an FTP server using
"OS.connectNonblocking" in place of "OS.connect" (pls. see attachment
"socket-test.oz").
It doesn't work. I get the following error, which, according to Stevens
("Unix Network Programming, Vol 1" by W. Richard Stevens, pp. 409-422)
is to be expected:
%*********************** error in OS module *********************
%**
%** Operating system error
%**
%** System call: connectNonblocking
%** Error number: 115
%** Description: In progress
%** In statement: {<P/3 OS.connectNonblocking> 3 '10.0.0.3' 21}
%**
%** Call Stack:
%** procedure in file "./socket-test.oz", line 1, column 0, PC = 135922072
%** procedure 'RootManager,Pickle/fast' in file
"/tmp/buildd/mozart-1.2.5.20030212/mozart/share/lib/init/Module.oz",
line 252, column 6, PC = 135901200
%** procedure in file
"/tmp/buildd/mozart-1.2.5.20030212/mozart/share/lib/init/Module.oz",
line 74, column 3, PC = 136084128
%**--------------------------------------------------------------
Actually, the change outlined in my original message should do the
trick. I just don't know how to suspend a thread and then resume it
later when a condition is met.
I've looked at the code in "components.cc" having to do with pipe
communication. Here, "OZ_registerReadHandler(rfd,pipeHandler,pi)" is
used to register a function called "pipeHandler" that will be called
when the "rfd" file-descriptor become readable. Then the macro
"SuspendOnControlVar" is used, I'm assuming to suspend the current
thread until "pipeHandler" is called.
Is this macro "SuspendOnControlVar" what is needed? Unfortunately,
there's no documentation on it, nor on what is needed in the registered
function to resume the thread once the registered function is called.
I could make and test this change, and then submit the diffs. Could you
let me know what to do, or is there some documentation I could reference
to steer me in the right direction?
Actually, my colleague (Fredrick Eisele) and I are probably going to
take over the Debian GNU/Linux package for Oz from Marco Kuhlmann, and
we're interested in the internals of the emulator. Could you give us
some references?
Thanks very much :)
-- Harmon
Konstantin Popov wrote:
>Dear Harmon,
>
>as a very first shot I'd suggest to have a look at the
>'OS.connectNonblocking' (which is actually used) and its
>implementation 'unix_connect_nonblocking()' in unix.cc.
>
>I take on record that we'd better document the thing in the next
>release - thank you for dragging the issue up.
>
>Cheers,
>
> --- Kostja.
>
>
>
>>Hello all. I'm using OZ in a multithreaded network application where it
>>is imperative that no thread cause the entire oz emulator to block.
>>
>>Unfortunately, as implemented, the "connect" function of the OS module
>>will block the entire oz-emulator, in particular if the connection
>>attempt is to a host that does not exist, or to a port on which there is
>>no service.
>>
>>"connect" can be made to be non-blocking (at least in UNIX) using a
>>method described in the book "Unix Network Programming, Vol. 1" by W.
>>Richard Stevens (pp. 409-422).
>>
>>However, I'm having trouble implementing this in the OZ code. I'm
>>certain that the osconnect() function in the file os.cc needs to be
>>changed to the following:
>>
>>
>>--- START CODE ---
>>int osconnect(int s, struct sockaddr *addr, int namelen)
>>{
>> osBlockSignals();
>>
>> // MAKE 's' NON-BLOCKING
>> int flags = fcntl(s, F_GETFL);
>> fcntl(s, F_SETFL, flags | O_NDELAY);
>>
>> // "connect" WILL NOT BLOCK
>> // "ret" WILL EITHER BE 0, INDICATING SUCCESSFUL connect,
>> // OR -1, WITH errno SET TO "EINPROGESS", INDICATING THAT connect
>> // IS NOT YET COMPLETE
>> int ret = connect(s,addr,namelen);
>>
>> // MAKE 's' BLOCKING AGAIN (PROBABLY DOESN'T MATTER)
>> fcntl(s, F_SETFL, flags); // MAKE '
>>
>> osUnblockSignals();
>> return ret;
>>}
>>---- END CODE ----
>>
>>Here's where I'm stuck:
>>
>>The function that calls osconnect, i.e. "unix_connectInet" in the
>>"unix.cc" file, needs to be changed to detect errno == EINPROGRESS, and
>>suspend the current thread until the file descriptor used in the connect
>>becomes writeable. The needed changes are outlined below:
>>
>>--- START CODE ---
>>OZ_BI_define(unix_connectInet,3,0)
>>{
>>
>> // ...
>>
>> int ret = osconnect(s,(struct sockaddr *) &addr,sizeof(addr));
>>
>> // CONNECT SUCCESSFUL
>> if (ret == 0) return PROCEED;
>>
>> // CONNECT STILL IN PROGRESS
>> if (errno == EINPROGRESS) {
>>
>> // SET UP "nbConnectCheck" TO BE CALLED BY OZ SCHEDULER
>> // WHEN 's' FILE DESCRIPTOR BECOMES WRITABLE
>> OZ_registerWriteHandler(s, nbConnectCheck, 0);
>>
>> // HELP! NEED TO SOMEHOW SUSPEND THE CURRENT THREAD
>> // AND HAVE IT RESUME WHEN 's' FILE DESCRIPTOR BECOMES WRITABLE.
>> // ...
>> }
>>
>> // BAD CONNECT
>> Assert(errno != EINTR);
>> RETURN_UNIX_ERROR("connect");
>>
>>} OZ_BI_end
>>
>>
>>int nbConnectCheck(int s, void *) {
>>
>> // HELP! NEED TO RESUME THREAD THAT WAS SUSPENDED ABOVE.
>>
>> int error;
>>
>> // ONCE 's' FILE DESCRIPTOR IS WRITABLE, CHECK STATUS WITH getsockopt
>> if ( getsockopt( s, SOL_SOCKET, SO_ERROR, &error, sizeof(error) ) <
>>0 ) {
>> RETURN_UNIX_ERROR("connect");
>> } else {
>> return PROCEED;
>> }
>>
>>}
>>---- END CODE ----
>>
>>Am I even on the right track here? Can someone tell me what to do, or
>>point me in the right direction?
>>
>>Any help would be *greatly appreciated*.
>>
>>Thanks
>>
>>-- Dr. Harmon S. Nine
>>
>>-
>>Please send submissions to hackers@mozart-oz.org
>>and administriva mail to hackers-request@mozart-oz.org.
>>The Mozart Oz web site is at http://www.mozart-oz.org/.
>>
>>
>-
>Please send submissions to hackers@mozart-oz.org
>and administriva mail to hackers-request@mozart-oz.org.
>The Mozart Oz web site is at http://www.mozart-oz.org/.
>
>
functor
import
Application
OS
Property
System
define
MySocket
InputHeader
InputTrailer
in
{Property.put 'print.width' 1000}
{Property.put 'print.depth' 1000}
MySocket = {OS.socket 'PF_INET' 'SOCK_STREAM' 'tcp'}
% {OS.connect MySocket '10.0.0.3' 21}
{OS.connectNonblocking MySocket '10.0.0.3' 21}
{OS.read MySocket 1024 InputHeader nil _}
{System.show 'InputHeader'#InputHeader}
{System.show 'Sending QUIT'}
{OS.write MySocket "QUIT\n" _}
{OS.read MySocket 1024 InputTrailer nil _}
{System.show 'InputTrailer'#InputTrailer}
{System.show 'Closing Socket'}
{OS.close MySocket}
{Application.exit 0}
end
-
Please send submissions to hackers@mozart-oz.org
and administriva mail to hackers-request@mozart-oz.org.
The Mozart Oz web site is at http://www.mozart-oz.org/.