xref: /aosp_15_r20/external/deqp/executor/xeLocalTcpIpLink.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Test Executor
3  * ------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Tcp/Ip link that manages execserver process.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "xeLocalTcpIpLink.hpp"
25 #include "deClock.h"
26 #include "deThread.h"
27 
28 #include <sstream>
29 
30 enum
31 {
32     SERVER_START_TIMEOUT    = 1000,
33     SERVER_START_IDLE_SLEEP = 50
34 };
35 
36 namespace xe
37 {
38 
LocalTcpIpLink(void)39 LocalTcpIpLink::LocalTcpIpLink(void) : m_process(DE_NULL)
40 {
41 }
42 
~LocalTcpIpLink(void)43 LocalTcpIpLink::~LocalTcpIpLink(void)
44 {
45     stop();
46 }
47 
start(const char * execServerPath,const char * workDir,int port)48 void LocalTcpIpLink::start(const char *execServerPath, const char *workDir, int port)
49 {
50     XE_CHECK(!m_process);
51 
52     std::ostringstream cmdLine;
53     cmdLine << execServerPath << " --single --port=" << port;
54 
55     m_process = deProcess_create();
56     XE_CHECK(m_process);
57 
58     if (deProcess_start(m_process, cmdLine.str().c_str(), workDir) != true)
59     {
60         std::string err = deProcess_getLastError(m_process);
61         deProcess_destroy(m_process);
62         m_process = DE_NULL;
63 
64         XE_FAIL((std::string("Failed to start ExecServer '") + execServerPath + "' : " + err).c_str());
65     }
66 
67     try
68     {
69         de::SocketAddress address;
70         address.setFamily(DE_SOCKETFAMILY_INET4);
71         address.setProtocol(DE_SOCKETPROTOCOL_TCP);
72         address.setHost("127.0.0.1");
73         address.setPort(port);
74 
75         // Wait until server has started - \todo [2012-07-19 pyry] This could be improved by having server to signal when it is ready.
76         uint64_t waitStart = deGetMicroseconds();
77         for (;;)
78         {
79             if (!deProcess_isRunning(m_process))
80                 XE_FAIL("ExecServer died");
81 
82             try
83             {
84                 m_link.connect(address);
85                 break;
86             }
87             catch (const de::SocketError &)
88             {
89                 if (deGetMicroseconds() - waitStart > SERVER_START_TIMEOUT * 1000)
90                     XE_FAIL("Server start timeout");
91 
92                 deSleep(SERVER_START_IDLE_SLEEP);
93             }
94         }
95 
96         // Close stdout/stderr or otherwise process will hang once OS pipe buffers are full.
97         // \todo [2012-07-19 pyry] Read and store stdout/stderr from execserver.
98         XE_CHECK(deProcess_closeStdOut(m_process));
99         XE_CHECK(deProcess_closeStdErr(m_process));
100     }
101     catch (const std::exception &)
102     {
103         stop();
104         throw;
105     }
106 }
107 
stop(void)108 void LocalTcpIpLink::stop(void)
109 {
110     if (m_process)
111     {
112         try
113         {
114             m_link.disconnect();
115         }
116         catch (...)
117         {
118             // Silently ignore since this is called in destructor.
119         }
120 
121         // \note --single flag is used so execserver should kill itself once one connection is handled.
122         //         This is here to make sure it dies even in case of hang.
123         deProcess_terminate(m_process);
124         deProcess_waitForFinish(m_process);
125         deProcess_destroy(m_process);
126 
127         m_process = DE_NULL;
128     }
129 }
130 
reset(void)131 void LocalTcpIpLink::reset(void)
132 {
133     m_link.reset();
134 }
135 
getState(void) const136 CommLinkState LocalTcpIpLink::getState(void) const
137 {
138     if (!m_process)
139         return COMMLINKSTATE_ERROR;
140     else
141         return m_link.getState();
142 }
143 
getState(std::string & error) const144 CommLinkState LocalTcpIpLink::getState(std::string &error) const
145 {
146     if (!m_process)
147     {
148         error = "Not started";
149         return COMMLINKSTATE_ERROR;
150     }
151     else
152         return m_link.getState();
153 }
154 
setCallbacks(StateChangedFunc stateChangedCallback,LogDataFunc testLogDataCallback,LogDataFunc infoLogDataCallback,void * userPtr)155 void LocalTcpIpLink::setCallbacks(StateChangedFunc stateChangedCallback, LogDataFunc testLogDataCallback,
156                                   LogDataFunc infoLogDataCallback, void *userPtr)
157 {
158     m_link.setCallbacks(stateChangedCallback, testLogDataCallback, infoLogDataCallback, userPtr);
159 }
160 
startTestProcess(const char * name,const char * params,const char * workingDir,const char * caseList)161 void LocalTcpIpLink::startTestProcess(const char *name, const char *params, const char *workingDir,
162                                       const char *caseList)
163 {
164     if (m_process)
165         m_link.startTestProcess(name, params, workingDir, caseList);
166     else
167         XE_FAIL("Not started");
168 }
169 
stopTestProcess(void)170 void LocalTcpIpLink::stopTestProcess(void)
171 {
172     if (m_process)
173         m_link.stopTestProcess();
174     else
175         XE_FAIL("Not started");
176 }
177 
178 } // namespace xe
179