Skip to main content

About 18 months ago I wrote a blog talking about changes in how accept works in OpenVOS release 17.1. What I neglected to indicate was that these changes only take effect if the application code is POSIX based. To recap, prior to 17.1 STCP would only reply to a client connection request if the server application code had called the accept routine. If the code had not called accept the client’s connection request would go into a queue but would not be answered. Once the application called accept, STCP would send a connection reply. If the client is still waiting, the connection completes at that time. If the client had already given up, it would respond to the connection reply with a reset, STCP would throw the connection away and the accept would hang (assuming blocking mode) and wait for another connection.

Figure 1 shows this scenario; the left justified text lines are status messages from the server application, the indented packet_monitor lines (slightly modified) are the result of client activity. The application (acceptTestnoPosix) is started and listens on port 12345, and once listening goes to sleep for 300 seconds. The client then makes a connection to port 12345 by sending a TCP segment to port 12345 with the Syn (S) flag set. It tries three times before giving up. After 300 seconds the application wakes up and calls accept. The STCP stack replies to the client with a TCP segment with the Syn and Ack (SA) flags set. Since the client no longer has a record of the connection if sends a Reset (R), STCP blocks at this point. If the socket were in non-blocking mode accept would have returned with an EAGAIN error.

acceptTestnoPosix 12345
Executing acceptTestnoPosix 12345
Sleeping for 300 seconds

  11:04:45.923 R TCP 164.152.77.50   164.152.77.217  11071  12345 S
  11:04:48.925 R TCP 164.152.77.50   164.152.77.217  11071  12345 S
  11:04:54.937 R TCP 164.152.77.50   164.152.77.217  11071  12345 S

Ready to accept a connection on port number 12345
  11:09:41.852 T TCP 164.152.77.217  164.152.77.50   12345  11071 SA 
  11:09:41.854 R TCP 164.152.77.50   164.152.77.217  11071  12345 R

Figure 1 – accept pre 17.1 or non-POSIX post 17.1

 

If the application is POSIX based, things are different (Figure 2). STCP replies to the connection request (S) immediately (SA). Then after 300 seconds the application wakes up, calls accept and STCP returns the accepted socket.

acceptTestwithPosix 12345
Executing acceptTestnoPosix 12345
Sleeping for 300 seconds

  10:58:43.962 R TCP 164.152.77.50   164.152.77.217  11024  12345 S
  10:58:43.964 T TCP 164.152.77.217  164.152.77.50   12345  11024 SA 
  10:58:43.964 R TCP 164.152.77.50   164.152.77.217  11024  12345 A

Ready to accept a connection on port number 12345
Connection accepted

Figure 2 – accept POSIX based post 17.1

 

The behavior difference can be critical. If the client is expecting a response from the server application after making a connection it may time out and close the connection before the application actually calls accept.

How do you build an application with POSIX? First the line

#define _POSIX_C_SOURCE 200112L

should be the first line of the application source. Second the library path

(master_disk)>system>posix_object_library

needs to be in the object library paths after the STCP libraries and before the C library.

How can you tell if this has been done? Well you can look at the object libraries that the application was bound with using the display_program_module -object_dirs command

display_program_module acceptTestwithPosix -object_dirs      
     %azvos#m17_mas>SysAdmin>Noah_Davids>temp>acceptTestwithPosix.pm 

Object Directory Map:

    11  search directories
     0  non-search directories
    11  directories in all

   DTC  Directory Path

     1  %azvos#m17_mas>SysAdmin>Noah_Davids>temp
     2  %azvos#m17_mas>system>stcp>object_library
     3  %azvos#m17_mas>system>stcp>object_library>socket
     4  %azvos#m17_mas>system>stcp>object_library>net
     5  %azvos#m17_mas>system>stcp>object_library>common
     6  %azvos#m17_mas>system>posix_object_library
     7  %azvos#m17_mas>system>c_object_library
     8  %azvos#m17_mas>system>object_library
     9  %azvos#m17_mas>opt>apache>lib
    10  %azvos#m17_mas>opt>openssl>lib
    11  %azvos#m17_mas>opt>mysql>lib>mysql

But this doesn’t tell you if the #define is part of the source code.

If you can run the code you can look at the socket flags, a POSIX based program will have the SF_POSIX socket flag set. For example, I have three programs acceptTestnoPosix, acceptTestwithPosix and acceptTestwithPosixPathOnly. This last one had the >system>posix_object_library directory in the library paths but did not include the #define in the source code. Note that this is considered an invalid combination. Only the application that was bound with the POSIX library and had the POSIX_SOURCE #define statement in the code created a socket with the SF_POSIX flag.

acceptTestnoPosix.pm 12345          
Executing acceptTestnoPosix 12345
Sleeping for 300 seconds
               as:  match posix; dump_stcbq -full -lport 12345       
               as:
acceptTestwithPosix.pm 12345
Executing acceptTestnoPosix 12345
Sleeping for 300 seconds
               as:  match posix; dump_stcbq -full -lport 12345
                                                   SF_POSIX
               as:  
acceptTestwithPosixPathOnly.pm 12345
Executing acceptTestnoPosix 12345
Sleeping for 300 seconds
               as:  match posix; dump_stcbq -full -lport 12345
               as:

There is a fourth possibility, the #define was included in the source but the posix_object_library was not used. In this case the socket routine will return an error.

acceptTestwithPosixDefineOnly 12345
Executing acceptTestnoPosix 12345
acceptTestnoPosix: can't create listening socket: Application built  
+  incorrectly: POSIX runtime must be searched before C runtime.

All of the STCP commands and utilities are built with POSIX and I strongly recommend that any applications you build also use POSIX.

© 2024 Stratus Technologies.