2 * Copyright 2016, Rene Gollent, rene@gollent.com.
3 * Copyright 2016, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Distributed under the terms of the MIT License.
7 #include "LocalTargetHostInterface.h"
16 #include <AutoDeleter.h>
17 #include <AutoLocker.h>
18 #include <system_info.h>
19 #include <util/KMessage.h>
21 #include "debug_utils.h"
24 #include "CoreFileDebuggerInterface.h"
25 #include "LocalDebuggerInterface.h"
26 #include "TargetHost.h"
30 LocalTargetHostInterface::LocalTargetHostInterface()
32 TargetHostInterface(),
40 LocalTargetHostInterface::~LocalTargetHostInterface()
44 if (fTargetHost
!= NULL
)
45 fTargetHost
->ReleaseReference();
50 LocalTargetHostInterface::Init(Settings
* settings
)
52 char hostname
[HOST_NAME_MAX
+ 1];
53 status_t error
= gethostname(hostname
, sizeof(hostname
));
57 fTargetHost
= new(std::nothrow
) TargetHost(hostname
);
58 if (fTargetHost
== NULL
)
62 error
= get_team_info(B_CURRENT_TEAM
, &info
);
67 snprintf(buffer
, sizeof(buffer
), "LocalTargetHostInterface %" B_PRId32
,
70 fDataPort
= create_port(100, buffer
);
74 fPortWorker
= spawn_thread(_PortLoop
, "Local Target Host Loop",
75 B_NORMAL_PRIORITY
, this);
79 resume_thread(fPortWorker
);
81 AutoLocker
<TargetHost
> hostLocker(fTargetHost
);
83 error
= __start_watching_system(-1,
84 B_WATCH_SYSTEM_TEAM_CREATION
| B_WATCH_SYSTEM_TEAM_DELETION
,
90 while (get_next_team_info(&cookie
, &info
) == B_OK
) {
91 error
= fTargetHost
->AddTeam(info
);
96 snprintf(buffer
, sizeof(buffer
), "Local (%s)", hostname
);
104 LocalTargetHostInterface::Close()
107 __stop_watching_system(-1,
108 B_WATCH_SYSTEM_TEAM_CREATION
| B_WATCH_SYSTEM_TEAM_DELETION
,
111 delete_port(fDataPort
);
115 if (fPortWorker
> 0) {
116 wait_for_thread(fPortWorker
, NULL
);
123 LocalTargetHostInterface::IsLocal() const
130 LocalTargetHostInterface::Connected() const
137 LocalTargetHostInterface::GetTargetHost()
144 LocalTargetHostInterface::Attach(team_id teamID
, thread_id threadID
,
145 DebuggerInterface
*& _interface
) const
147 if (teamID
< 0 && threadID
< 0)
152 thread_info threadInfo
;
153 error
= get_thread_info(threadID
, &threadInfo
);
157 teamID
= threadInfo
.team
;
160 LocalDebuggerInterface
* interface
161 = new(std::nothrow
) LocalDebuggerInterface(teamID
);
162 if (interface
== NULL
)
165 BReference
<DebuggerInterface
> interfaceReference(interface
, true);
166 error
= interface
->Init();
170 _interface
= interface
;
171 interfaceReference
.Detach();
177 LocalTargetHostInterface::CreateTeam(int commandLineArgc
,
178 const char* const* arguments
, team_id
& _teamID
) const
180 thread_id thread
= load_program(arguments
, commandLineArgc
, false);
184 // main thread ID == team ID.
191 LocalTargetHostInterface::LoadCore(const char* coreFilePath
,
192 DebuggerInterface
*& _interface
, thread_id
& _thread
) const
194 // load the core file
195 CoreFile
* coreFile
= new(std::nothrow
) CoreFile
;
196 if (coreFile
== NULL
)
198 ObjectDeleter
<CoreFile
> coreFileDeleter(coreFile
);
200 status_t error
= coreFile
->Init(coreFilePath
);
204 // create the debugger interface
205 CoreFileDebuggerInterface
* interface
206 = new(std::nothrow
) CoreFileDebuggerInterface(coreFile
);
207 if (interface
== NULL
)
209 coreFileDeleter
.Detach();
211 BReference
<DebuggerInterface
> interfaceReference(interface
, true);
212 error
= interface
->Init();
216 const CoreFileTeamInfo
& teamInfo
= coreFile
->GetTeamInfo();
217 _thread
= teamInfo
.Id();
218 _interface
= interface
;
219 interfaceReference
.Detach();
226 LocalTargetHostInterface::FindTeamByThread(thread_id thread
,
227 team_id
& _teamID
) const
230 status_t error
= get_thread_info(thread
, &info
);
240 LocalTargetHostInterface::_PortLoop(void* arg
)
242 LocalTargetHostInterface
* interface
= (LocalTargetHostInterface
*)arg
;
243 set
<team_id
> waitingTeams
;
252 ssize_t size
= read_port_etc(interface
->fDataPort
, &messageCode
,
253 buffer
, sizeof(buffer
), B_TIMEOUT
, waitingTeams
.empty()
254 ? B_INFINITE_TIMEOUT
: 20000);
255 if (size
== B_INTERRUPTED
)
257 else if (size
== B_TIMED_OUT
&& !waitingTeams
.empty()) {
258 for (set
<team_id
>::iterator it
= waitingTeams
.begin();
259 it
!= waitingTeams
.end(); ++it
) {
261 error
= interface
->_HandleTeamEvent(team
,
262 B_TEAM_CREATED
, addToWaiters
);
265 else if (!addToWaiters
) {
266 waitingTeams
.erase(it
);
267 if (waitingTeams
.empty())
269 it
= waitingTeams
.begin();
277 size
= message
.SetTo(buffer
);
281 if (message
.What() != B_SYSTEM_OBJECT_UPDATE
)
285 if (message
.FindInt32("opcode", &opcode
) != B_OK
)
289 if (message
.FindInt32("team", &team
) != B_OK
)
292 error
= interface
->_HandleTeamEvent(team
, opcode
,
296 if (opcode
== B_TEAM_CREATED
&& addToWaiters
) {
298 waitingTeams
.insert(team
);
310 LocalTargetHostInterface::_HandleTeamEvent(team_id team
, int32 opcode
,
313 addToWaiters
= false;
314 AutoLocker
<TargetHost
> locker(fTargetHost
);
320 status_t error
= get_team_info(team
, &info
);
321 // this team is already gone, no point in sending a notification
322 if (error
== B_BAD_TEAM_ID
)
324 else if (error
!= B_OK
)
328 image_info imageInfo
;
330 while (get_next_image_info(team
, &cookie
, &imageInfo
)
332 if (imageInfo
.type
== B_APP_IMAGE
) {
333 addToWaiters
= false;
341 if (opcode
== B_TEAM_CREATED
)
342 fTargetHost
->AddTeam(info
);
344 fTargetHost
->UpdateTeam(info
);
350 fTargetHost
->RemoveTeam(team
);