Merge lp:~widelands-dev/widelands/network-memory into lp:widelands

Proposed by GunChleoc
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
Reviewer Review Type Date Requested Status
Klaus Halfmann compile / test Approve
Review via email: mp+286162@code.launchpad.net

Commit message

InternetGaming::games() and InternetGaming::clients() now return nullptr instead of a new vector in case of a communication failure.

Description of the change

This is a fix for a potential memory leak flagged up by Hasi50.

To post a comment you must log in.
Revision history for this message
SirVer (sirver) wrote :

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.

Revision history for this message
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.

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 716. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/109585303.
Appveyor build 563. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_network_memory-563.

Revision history for this message
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.

Revision history for this message
GunChleoc (gunchleoc) wrote :

Maybe we could show a message to indicate the error somehow?

Revision history for this message
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/klaus/develop/widelands-repo/network-memory/src/network/internet_gaming.cc, line 139.

The "Solution" in Java is returning an immutable vector.
No idea how to do this in C++ perhpas some const& const, whatever...

Revision history for this message
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://bazaar.launchpad.net/~widelands-dev/widelands/network-memory/

Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 736. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/110471430.
Appveyor build 582. State: success. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_network_memory-582.

Revision history for this message
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.

review: Approve (compile / test)
Revision history for this message
GunChleoc (gunchleoc) wrote :

@bunnybot merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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

Subscribers

People subscribed via source and target branches

to status/vote changes: