2828
2929#include < boost/thread.hpp>
3030#include < string>
31+ #include < utility>
3132#include < cassert>
33+ #include < cstring>
34+ #include < unistd.h>
35+ #include < LoggingKit/Logging.h>
3236#include < IOTools/IOUtils.h>
3337#include < IOTools/BufferedIO.h>
38+ #include < StrIntTools/StrIntUtils.h>
3439#include < Core/ApplicationPool/AbstractSession.h>
40+ #include < Exceptions.h>
41+ #include < StaticString.h>
42+ #include < FileDescriptor.h>
43+ #include < Utils.h>
44+ #include < Utils/ScopeGuard.h>
45+ #include < FileTools/FileManip.h>
46+ #include < oxt/system_calls.hpp>
3547
3648namespace Passenger {
3749namespace ApplicationPool2 {
@@ -57,6 +69,7 @@ class TestSession: public AbstractSession {
5769 mutable bool closed;
5870 mutable bool success;
5971 mutable bool wantKeepAlive;
72+ mutable bool forcingNonInstantConnect;
6073
6174public:
6275 TestSession ()
@@ -67,7 +80,8 @@ class TestSession: public AbstractSession {
6780 stickySessionId(0 ),
6881 closed(false ),
6982 success(false ),
70- wantKeepAlive(false )
83+ wantKeepAlive(false ),
84+ forcingNonInstantConnect(false )
7185 { }
7286
7387 virtual void ref () const override {
@@ -163,12 +177,57 @@ class TestSession: public AbstractSession {
163177 return wantKeepAlive;
164178 }
165179
166- virtual void initiate ( bool blocking = true ) override {
180+ void forceNonInstantConnect () {
167181 boost::lock_guard<boost::mutex> l (syncher);
168- connection = createUnixSocketPair (__FILE__, __LINE__);
182+ forcingNonInstantConnect = true ;
183+ }
184+
185+ virtual bool initiate () override {
186+ boost::lock_guard<boost::mutex> l (syncher);
187+
188+ // Create a unique temporary directory for the socket
189+ string tempDirPathTemplate = StaticString (getSystemTempDir ()) + " /passenger.session.XXXXXX" ;
190+ DynamicBuffer tempDirPath (tempDirPathTemplate.size () + 1 );
191+ memcpy (tempDirPath.data , tempDirPathTemplate.c_str (), tempDirPathTemplate.size () + 1 );
192+ if (mkdtemp (tempDirPath.data ) == NULL ) {
193+ int e = errno;
194+ throw SystemException (" Cannot create temporary directory" , e);
195+ }
196+ ScopeGuard g ([&]() {
197+ try {
198+ removeDirTree (tempDirPath.data );
199+ } catch (const std::exception &e) {
200+ P_ERROR (" Error deleting temporary directory " << tempDirPath.data << " : " << e.what ());
201+ }
202+ });
203+
204+ // Create server socket
205+ string socketPath = StaticString (tempDirPath.data ) + " /socket" ;
206+ FileDescriptor serverFd (createUnixServer (socketPath.c_str (), 0 , true , __FILE__, __LINE__),
207+ __FILE__, __LINE__);
208+
209+ // Create client socket (non-blocking)
210+ NUnix_State clientState;
211+ setupNonBlockingUnixSocket (clientState, socketPath, __FILE__, __LINE__);
212+ bool immediatelyConnected = connectToUnixServer (clientState);
213+ connection.first = std::move (clientState.fd );
214+
215+ // Accept connection (blocking)
216+ FileDescriptor serverSideFd (oxt::syscalls::accept (serverFd, NULL , NULL ),
217+ __FILE__, __LINE__);
218+ if (serverSideFd == -1 ) {
219+ int e = errno;
220+ throw SystemException (" Cannot accept connection" , e);
221+ }
222+
223+ // Store the server-side fd.
224+ connection.second = std::move (serverSideFd);
169225 peerBufferedIO = BufferedIO (connection.second );
170- if (!blocking) {
171- setNonBlocking (connection.first );
226+
227+ if (forcingNonInstantConnect) {
228+ return false ;
229+ } else {
230+ return immediatelyConnected;
172231 }
173232 }
174233
0 commit comments