Merge lp:~widelands-dev/widelands/network-memory into lp:widelands
- network-memory
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 7848 |
Proposed branch: | lp:~widelands-dev/widelands/network-memory |
Merge into: | lp:widelands |
Diff against target: |
437 lines (+124/-116) 4 files modified
src/network/internet_gaming.cc (+6/-8) src/network/internet_gaming.h (+2/-2) src/ui_fsmenu/internet_lobby.cc (+107/-97) src/ui_fsmenu/internet_lobby.h (+9/-9) |
To merge this branch: | bzr merge lp:~widelands-dev/widelands/network-memory |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Klaus Halfmann | compile / test | Approve | |
Review via email: mp+286162@code.launchpad.net |
Commit message
InternetGaming:
Description of the change
This is a fix for a potential memory leak flagged up by Hasi50.
SirVer (sirver) wrote : | # |
GunChleoc (gunchleoc) wrote : | # |
The vector member variable is being kept around - the new vector was only being created locally in the function in case of communication error. I say it makes sense in case of a communication error to simply not update anything.
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 716. State: passed. Details: https:/
Appveyor build 563. State: failed. Details: https:/
Klaus Halfmann (klaus-halfmann) wrote : | # |
Mhh, you canged the semantics:
* now: on Error you do not update anything.
* old: on Error list whre made empty (to indicate the error)
I will play a round with trunk to find how it looks like and then compare wiht this branch.
GunChleoc (gunchleoc) wrote : | # |
Maybe we could show a message to indicate the error somehow?
Klaus Halfmann (klaus-halfmann) wrote : | # |
Pulling the network cable and then trying to go along the internet game gave me:
InternetGaming: reached a timeout for an awaited answer of the metaserver!
InternetGaming: Connecting to the metaserver.
Warning: Verbindungsproblem
Widelands konnte sich nicht zum Metaserver verbinden.
Assertion failed: (state_ == OFFLINE), function login, file /Users/
The "Solution" in Java is returning an immutable vector.
No idea how to do this in C++ perhpas some const& const, whatever...
bunnybot (widelandsofficial) wrote : | # |
Bunnybot encountered an error while working on this merge proposal:
Running 'bzr pull --overwrite' failed. Output:
Permission denied (publickey).
ConnectionReset reading response for 'BzrDir.open_2.1', retrying
Permission denied (publickey).
bzr: ERROR: Connection closed: Unexpected end of message. Please check connectivity and permissions, and report a bug if problems persist.
Using saved parent location: bzr+ssh:
bunnybot (widelandsofficial) wrote : | # |
Continuous integration builds have changed state:
Travis build 736. State: passed. Details: https:/
Appveyor build 582. State: success. Details: https:/
Klaus Halfmann (klaus-halfmann) wrote : | # |
Compiles, did some test with Gun, which foound bug #1542821 but this is the same in trunk.
Maybe some lists will stay in some other state now, but as of the networking error there
is no consistent state anyway.
OTOH we get rid of some memory leaks.
GunChleoc (gunchleoc) wrote : | # |
@bunnybot merge
Preview Diff
1 | === modified file 'src/network/internet_gaming.cc' |
2 | --- src/network/internet_gaming.cc 2016-02-15 12:35:10 +0000 |
3 | +++ src/network/internet_gaming.cc 2016-02-19 20:11:01 +0000 |
4 | @@ -721,10 +721,9 @@ |
5 | |
6 | |
7 | |
8 | -/// \returns the tables in the room, if no error occured |
9 | -const std::vector<InternetGame> & InternetGaming::games() { |
10 | - // TODO(Hasi50): in case of error() this is a memory leak? should return some unmodifiable singleton. |
11 | - return error() ? * (new std::vector<InternetGame>()) : gamelist_; |
12 | +/// \returns the tables in the room, if no error occured, or nullptr in case of error |
13 | +const std::vector<InternetGame>* InternetGaming::games() { |
14 | + return error() ? nullptr : &gamelist_; |
15 | } |
16 | |
17 | |
18 | @@ -739,10 +738,9 @@ |
19 | |
20 | |
21 | |
22 | -/// \returns the players in the room, if no error occured |
23 | -const std::vector<InternetClient> & InternetGaming::clients() { |
24 | - // TODO(Hasi50): in case of error() this is a memory leak? should return some unmodifiable singleton. |
25 | - return error() ? * (new std::vector<InternetClient>()) : clientlist_; |
26 | +/// \returns the players in the room, if no error occured, or nullptr in case of error |
27 | +const std::vector<InternetClient>* InternetGaming::clients() { |
28 | + return error() ? nullptr : &clientlist_; |
29 | } |
30 | |
31 | |
32 | |
33 | === modified file 'src/network/internet_gaming.h' |
34 | --- src/network/internet_gaming.h 2016-02-15 12:35:10 +0000 |
35 | +++ src/network/internet_gaming.h 2016-02-19 20:11:01 +0000 |
36 | @@ -86,9 +86,9 @@ |
37 | |
38 | // Informative functions for lobby |
39 | bool update_for_games(); |
40 | - const std::vector<InternetGame> & games(); |
41 | + const std::vector<InternetGame>* games(); |
42 | bool update_for_clients(); |
43 | - const std::vector<InternetClient> & clients(); |
44 | + const std::vector<InternetClient>* clients(); |
45 | |
46 | /// sets the name of the local server as shown in the games list |
47 | void set_local_servername(const std::string & name) {gamename_ = name;} |
48 | |
49 | === modified file 'src/ui_fsmenu/internet_lobby.cc' |
50 | --- src/ui_fsmenu/internet_lobby.cc 2016-02-07 16:31:06 +0000 |
51 | +++ src/ui_fsmenu/internet_lobby.cc 2016-02-19 20:11:01 +0000 |
52 | @@ -66,33 +66,33 @@ |
53 | _("Name of your server:")), |
54 | |
55 | // Buttons |
56 | - joingame |
57 | + joingame_ |
58 | (this, "join_game", |
59 | get_w() * 17 / 25, get_h() * 55 / 100, butw_, buth_, |
60 | g_gr->images().get("images/ui_basic/but1.png"), |
61 | _("Join this game"), std::string(), false, false), |
62 | - hostgame |
63 | + hostgame_ |
64 | (this, "host_game", |
65 | get_w() * 17 / 25, get_h() * 81 / 100, butw_, buth_, |
66 | g_gr->images().get("images/ui_basic/but1.png"), |
67 | _("Open a new game"), std::string(), true, false), |
68 | - back |
69 | + back_ |
70 | (this, "back", |
71 | get_w() * 17 / 25, get_h() * 90 / 100, butw_, buth_, |
72 | g_gr->images().get("images/ui_basic/but0.png"), |
73 | _("Back"), std::string(), true, false), |
74 | |
75 | // Edit boxes |
76 | - servername |
77 | + edit_servername_ |
78 | (this, get_w() * 17 / 25, get_h() * 68 / 100, butw_, |
79 | g_gr->images().get("images/ui_basic/but2.png"), fs_), |
80 | |
81 | // List |
82 | - clientsonline |
83 | + clientsonline_list_ |
84 | (this, |
85 | get_w() * 4 / 125, get_h() / 5, |
86 | lisw_, get_h() * 3 / 10), |
87 | - opengames |
88 | + opengames_list_ |
89 | (this, |
90 | get_w() * 17 / 25, get_h() / 5, |
91 | butw_, get_h() * 7 / 20), |
92 | @@ -105,15 +105,15 @@ |
93 | InternetGaming::ref()), |
94 | |
95 | // Login information |
96 | - nickname(nick), |
97 | - password(pwd), |
98 | - reg(registered) |
99 | + nickname_(nick), |
100 | + password_(pwd), |
101 | + is_registered_(registered) |
102 | { |
103 | - joingame.sigclicked.connect( |
104 | + joingame_.sigclicked.connect( |
105 | boost::bind(&FullscreenMenuInternetLobby::clicked_joingame, boost::ref(*this))); |
106 | - hostgame.sigclicked.connect( |
107 | + hostgame_.sigclicked.connect( |
108 | boost::bind(&FullscreenMenuInternetLobby::clicked_hostgame, boost::ref(*this))); |
109 | - back.sigclicked.connect(boost::bind(&FullscreenMenuInternetLobby::clicked_back, boost::ref(*this))); |
110 | + back_.sigclicked.connect(boost::bind(&FullscreenMenuInternetLobby::clicked_back, boost::ref(*this))); |
111 | |
112 | // Set the texts and style of UI elements |
113 | Section & s = g_options.pull_section("global"); // for playername |
114 | @@ -123,8 +123,8 @@ |
115 | clients_ .set_fontsize(fs_); |
116 | servername_.set_fontsize(fs_); |
117 | std::string server = s.get_string("servername", ""); |
118 | - servername .set_text (server); |
119 | - servername .changed.connect |
120 | + edit_servername_ .set_text (server); |
121 | + edit_servername_ .changed.connect |
122 | (boost::bind(&FullscreenMenuInternetLobby::change_servername, this)); |
123 | |
124 | // prepare the lists |
125 | @@ -139,19 +139,19 @@ |
126 | % "<br><img src=images/wui/overlays/roadb_red.png> " |
127 | % _("Unregistered") |
128 | % "</p></rt>").str(); |
129 | - clientsonline .add_column(22, "*", t_tip); |
130 | + clientsonline_list_ .add_column(22, "*", t_tip); |
131 | /** TRANSLATORS: Player Name */ |
132 | - clientsonline .add_column((lisw_ - 22) * 3 / 8, pgettext("player", "Name")); |
133 | - clientsonline .add_column((lisw_ - 22) * 2 / 8, _("Points")); |
134 | - clientsonline .add_column((lisw_ - 22) * 3 / 8, _("Game")); |
135 | - clientsonline.set_column_compare |
136 | + clientsonline_list_ .add_column((lisw_ - 22) * 3 / 8, pgettext("player", "Name")); |
137 | + clientsonline_list_ .add_column((lisw_ - 22) * 2 / 8, _("Points")); |
138 | + clientsonline_list_ .add_column((lisw_ - 22) * 3 / 8, _("Game")); |
139 | + clientsonline_list_.set_column_compare |
140 | (0, boost::bind(&FullscreenMenuInternetLobby::compare_clienttype, this, _1, _2)); |
141 | - clientsonline .double_clicked.connect |
142 | + clientsonline_list_ .double_clicked.connect |
143 | (boost::bind(&FullscreenMenuInternetLobby::client_doubleclicked, this, _1)); |
144 | - opengames .set_fontsize(fs_); |
145 | - opengames .selected.connect |
146 | + opengames_list_ .set_fontsize(fs_); |
147 | + opengames_list_ .selected.connect |
148 | (boost::bind(&FullscreenMenuInternetLobby::server_selected, this)); |
149 | - opengames .double_clicked.connect |
150 | + opengames_list_ .double_clicked.connect |
151 | (boost::bind(&FullscreenMenuInternetLobby::server_doubleclicked, this)); |
152 | |
153 | // try to connect to the metaserver |
154 | @@ -176,16 +176,18 @@ |
155 | InternetGaming::ref().handle_metaserver_communication(); |
156 | } |
157 | |
158 | - if (InternetGaming::ref().update_for_clients()) |
159 | + if (InternetGaming::ref().update_for_clients()) { |
160 | fill_client_list(InternetGaming::ref().clients()); |
161 | + } |
162 | |
163 | - if (InternetGaming::ref().update_for_games()) |
164 | + if (InternetGaming::ref().update_for_games()) { |
165 | fill_games_list(InternetGaming::ref().games()); |
166 | + } |
167 | } |
168 | |
169 | void FullscreenMenuInternetLobby::clicked_ok() |
170 | { |
171 | - if (joingame.enabled()) { |
172 | + if (joingame_.enabled()) { |
173 | server_doubleclicked(); |
174 | } else { |
175 | clicked_hostgame(); |
176 | @@ -201,35 +203,40 @@ |
177 | const std::string & metaserver = s.get_string("metaserver", INTERNET_GAMING_METASERVER.c_str()); |
178 | uint32_t port = s.get_natural("metaserverport", INTERNET_GAMING_PORT); |
179 | |
180 | - InternetGaming::ref().login(nickname, password, reg, metaserver, port); |
181 | + InternetGaming::ref().login(nickname_, password_, is_registered_, metaserver, port); |
182 | } |
183 | |
184 | |
185 | /// fills the server list |
186 | -void FullscreenMenuInternetLobby::fill_games_list(const std::vector<InternetGame> & games) |
187 | +void FullscreenMenuInternetLobby::fill_games_list(const std::vector<InternetGame>* games) |
188 | { |
189 | // List and button cleanup |
190 | - opengames.clear(); |
191 | - hostgame.set_enabled(true); |
192 | - joingame.set_enabled(false); |
193 | - std::string localservername = servername.text(); |
194 | - for (uint32_t i = 0; i < games.size(); ++i) { |
195 | - const Image* pic; |
196 | - if (games.at(i).connectable) { |
197 | - if (games.at(i).build_id == build_id()) |
198 | - pic = g_gr->images().get("images/ui_basic/continue.png"); |
199 | - else { |
200 | - pic = g_gr->images().get("images/ui_basic/different.png"); |
201 | - } |
202 | - } else { |
203 | - pic = g_gr->images().get("images/ui_basic/stop.png"); |
204 | + opengames_list_.clear(); |
205 | + hostgame_.set_enabled(true); |
206 | + joingame_.set_enabled(false); |
207 | + std::string localservername = edit_servername_.text(); |
208 | + |
209 | + if (games != nullptr) { // If no communication error occurred, fill the list. |
210 | + for (uint32_t i = 0; i < games->size(); ++i) { |
211 | + const Image* pic; |
212 | + const InternetGame& game = games->at(i); |
213 | + if (game.connectable) { |
214 | + if (game.build_id == build_id()) |
215 | + pic = g_gr->images().get("images/ui_basic/continue.png"); |
216 | + else { |
217 | + pic = g_gr->images().get("images/ui_basic/different.png"); |
218 | + } |
219 | + } else { |
220 | + pic = g_gr->images().get("images/ui_basic/stop.png"); |
221 | + } |
222 | + // If one of the servers has the same name as the local name of the |
223 | + // clients server, we disable the 'hostgame' button to avoid having more |
224 | + // than one server with the same name. |
225 | + if (game.name == localservername) { |
226 | + hostgame_.set_enabled(false); |
227 | + } |
228 | + opengames_list_.add(game.name, game, pic, false, game.build_id); |
229 | } |
230 | - // If one of the servers has the same name as the local name of the |
231 | - // clients server, we disable the 'hostgame' button to avoid having more |
232 | - // than one server with the same name. |
233 | - if (games.at(i).name == localservername) |
234 | - hostgame.set_enabled(false); |
235 | - opengames.add(games.at(i).name, games.at(i), pic, false, games.at(i).build_id); |
236 | } |
237 | } |
238 | |
239 | @@ -252,51 +259,51 @@ |
240 | */ |
241 | bool FullscreenMenuInternetLobby::compare_clienttype(unsigned int rowa, unsigned int rowb) |
242 | { |
243 | - const InternetClient * playera = clientsonline[rowa]; |
244 | - const InternetClient * playerb = clientsonline[rowb]; |
245 | + const InternetClient * playera = clientsonline_list_[rowa]; |
246 | + const InternetClient * playerb = clientsonline_list_[rowb]; |
247 | |
248 | return convert_clienttype(playera->type) < convert_clienttype(playerb->type); |
249 | } |
250 | |
251 | /// fills the client list |
252 | -void FullscreenMenuInternetLobby::fill_client_list(const std::vector<InternetClient> & clients) |
253 | +void FullscreenMenuInternetLobby::fill_client_list(const std::vector<InternetClient>* clients) |
254 | { |
255 | - clientsonline.clear(); |
256 | - for (uint32_t i = 0; i < clients.size(); ++i) { |
257 | - const InternetClient & client(clients[i]); |
258 | - UI::Table<const InternetClient * const>::EntryRecord & er = clientsonline.add(&client); |
259 | - er.set_string(1, client.name); |
260 | - er.set_string(2, client.points); |
261 | - er.set_string(3, client.game); |
262 | + clientsonline_list_.clear(); |
263 | + if (clients != nullptr) { // If no communication error occurred, fill the list. |
264 | + for (uint32_t i = 0; i < clients->size(); ++i) { |
265 | + const InternetClient& client(clients->at(i)); |
266 | + UI::Table<const InternetClient * const>::EntryRecord & er = clientsonline_list_.add(&client); |
267 | + er.set_string(1, client.name); |
268 | + er.set_string(2, client.points); |
269 | + er.set_string(3, client.game); |
270 | |
271 | - const Image* pic; |
272 | - switch (convert_clienttype(client.type)) { |
273 | - case 0: // UNREGISTERED |
274 | - pic = g_gr->images().get("images/wui/overlays/roadb_red.png"); |
275 | - er.set_picture(0, pic); |
276 | - break; |
277 | - case 1: // REGISTERED |
278 | - pic = g_gr->images().get("images/wui/overlays/roadb_yellow.png"); |
279 | - er.set_picture(0, pic); |
280 | - break; |
281 | - case 2: // SUPERUSER |
282 | - case 3: // BOT |
283 | - pic = g_gr->images().get("images/wui/overlays/roadb_green.png"); |
284 | - er.set_color(RGBColor(0, 255, 0)); |
285 | - er.set_picture(0, pic); |
286 | - break; |
287 | - default: |
288 | - continue; |
289 | + const Image* pic; |
290 | + switch (convert_clienttype(client.type)) { |
291 | + case 0: // UNREGISTERED |
292 | + pic = g_gr->images().get("images/wui/overlays/roadb_red.png"); |
293 | + er.set_picture(0, pic); |
294 | + break; |
295 | + case 1: // REGISTERED |
296 | + pic = g_gr->images().get("images/wui/overlays/roadb_yellow.png"); |
297 | + er.set_picture(0, pic); |
298 | + break; |
299 | + case 2: // SUPERUSER |
300 | + case 3: // BOT |
301 | + pic = g_gr->images().get("images/wui/overlays/roadb_green.png"); |
302 | + er.set_color(RGBColor(0, 255, 0)); |
303 | + er.set_picture(0, pic); |
304 | + break; |
305 | + default: |
306 | + continue; |
307 | + } |
308 | } |
309 | } |
310 | |
311 | // If a new player joins the lobby, play a sound. |
312 | - if (clients.size() != prev_clientlist_len_) |
313 | - { |
314 | - if (clients.size() > prev_clientlist_len_ && !InternetGaming::ref().sound_off()) |
315 | - play_new_chat_member(); |
316 | - prev_clientlist_len_ = clients.size(); |
317 | + if (clients->size() > prev_clientlist_len_ && !InternetGaming::ref().sound_off()) { |
318 | + play_new_chat_member(); |
319 | } |
320 | + prev_clientlist_len_ = clients->size(); |
321 | } |
322 | |
323 | |
324 | @@ -304,8 +311,8 @@ |
325 | void FullscreenMenuInternetLobby::client_doubleclicked (uint32_t i) |
326 | { |
327 | // add a @clientname to the current edit text. |
328 | - if (clientsonline.has_selection()) { |
329 | - UI::Table<const InternetClient * const>::EntryRecord & er = clientsonline.get_record(i); |
330 | + if (clientsonline_list_.has_selection()) { |
331 | + UI::Table<const InternetClient * const>::EntryRecord & er = clientsonline_list_.get_record(i); |
332 | |
333 | std::string temp("@"); |
334 | temp += er.get_string(1); |
335 | @@ -329,12 +336,12 @@ |
336 | /// called when an entry of the server list was selected |
337 | void FullscreenMenuInternetLobby::server_selected() |
338 | { |
339 | - if (opengames.has_selection()) { |
340 | - const InternetGame * game = &opengames.get_selected(); |
341 | + if (opengames_list_.has_selection()) { |
342 | + const InternetGame * game = &opengames_list_.get_selected(); |
343 | if (game->connectable) |
344 | - joingame.set_enabled(true); |
345 | + joingame_.set_enabled(true); |
346 | else |
347 | - joingame.set_enabled(false); |
348 | + joingame_.set_enabled(false); |
349 | } |
350 | } |
351 | |
352 | @@ -343,8 +350,8 @@ |
353 | void FullscreenMenuInternetLobby::server_doubleclicked() |
354 | { |
355 | // if the game is open try to connect it, if not do nothing. |
356 | - if (opengames.has_selection()) { |
357 | - const InternetGame * game = &opengames.get_selected(); |
358 | + if (opengames_list_.has_selection()) { |
359 | + const InternetGame * game = &opengames_list_.get_selected(); |
360 | if (game->connectable) |
361 | clicked_joingame(); |
362 | } |
363 | @@ -355,14 +362,17 @@ |
364 | void FullscreenMenuInternetLobby::change_servername() |
365 | { |
366 | // Allow client to enter a servername manually |
367 | - hostgame.set_enabled(true); |
368 | + hostgame_.set_enabled(true); |
369 | |
370 | // Check whether a server of that name is already open. |
371 | // And disable 'hostgame' button if yes. |
372 | - const std::vector<InternetGame> & games = InternetGaming::ref().games(); |
373 | - for (uint32_t i = 0; i < games.size(); ++i) { |
374 | - if (games.at(i).name == servername.text()) |
375 | - hostgame.set_enabled(false); |
376 | + const std::vector<InternetGame>* games = InternetGaming::ref().games(); |
377 | + if (games != nullptr) { |
378 | + for (uint32_t i = 0; i < games->size(); ++i) { |
379 | + if (games->at(i).name == edit_servername_.text()) { |
380 | + hostgame_.set_enabled(false); |
381 | + } |
382 | + } |
383 | } |
384 | } |
385 | |
386 | @@ -370,8 +380,8 @@ |
387 | /// called when the 'join game' button was clicked |
388 | void FullscreenMenuInternetLobby::clicked_joingame() |
389 | { |
390 | - if (opengames.has_selection()) { |
391 | - InternetGaming::ref().join_game(opengames.get_selected().name); |
392 | + if (opengames_list_.has_selection()) { |
393 | + InternetGaming::ref().join_game(opengames_list_.get_selected().name); |
394 | |
395 | uint32_t const secs = time(nullptr); |
396 | while (InternetGaming::ref().ip().size() < 1) { |
397 | @@ -431,7 +441,7 @@ |
398 | void FullscreenMenuInternetLobby::clicked_hostgame() |
399 | { |
400 | // Save selected servername as default for next time and during that take care that the name is not empty. |
401 | - std::string servername_ui = servername.text(); |
402 | + std::string servername_ui = edit_servername_.text(); |
403 | if (servername_ui.empty()) { |
404 | /** TRANSLATORS: This is shown for multiplayer games when no host */ |
405 | /** TRANSLATORS: server to connect to has been specified yet. */ |
406 | |
407 | === modified file 'src/ui_fsmenu/internet_lobby.h' |
408 | --- src/ui_fsmenu/internet_lobby.h 2016-02-07 16:31:06 +0000 |
409 | +++ src/ui_fsmenu/internet_lobby.h 2016-02-19 20:11:01 +0000 |
410 | @@ -52,19 +52,19 @@ |
411 | uint32_t prev_clientlist_len_; |
412 | UI::Textarea title, clients_, opengames_; |
413 | UI::Textarea servername_; |
414 | - UI::Button joingame, hostgame, back; |
415 | - UI::EditBox servername; |
416 | - UI::Table<const InternetClient * const> clientsonline; |
417 | - UI::Listselect<InternetGame> opengames; |
418 | + UI::Button joingame_, hostgame_, back_; |
419 | + UI::EditBox edit_servername_; |
420 | + UI::Table<const InternetClient * const> clientsonline_list_; |
421 | + UI::Listselect<InternetGame> opengames_list_; |
422 | GameChatPanel chat; |
423 | |
424 | // Login information |
425 | - const char * nickname; |
426 | - const char * password; |
427 | - bool reg; |
428 | + const char * nickname_; |
429 | + const char * password_; |
430 | + bool is_registered_; |
431 | |
432 | - void fill_games_list (const std::vector<InternetGame> &); |
433 | - void fill_client_list(const std::vector<InternetClient> &); |
434 | + void fill_games_list (const std::vector<InternetGame>*); |
435 | + void fill_client_list(const std::vector<InternetClient>*); |
436 | |
437 | void connect_to_metaserver(); |
438 |
I think it would be better to just always keep a vector around and just keep it empty. Dealign with new/delete for vectors is fragile, and the vector has its memory on the heap anyways, so keeping it around is basically free.
This is only a comment though, I have no time to properly dig into the code review till the weekend.