I'm writing a server for an online game based on IOCP, and the core codes handling game message is something like below:
CMessage ret;
int now_roomnum = recv_msg->para1;
int now_playernum = recv_msg->para2;
/*if(true)
{
cout<<"Received Game Message: "<<endl;
cout<<"type2 = "<<recv_msg->type2;
cout<<" player_num = "<<now_playernum<<" msg= "<<recv_msg->msg<<endl;
cout<<endl;
}*/
if(recv_msg->type2 == MSG_GAME_OPERATION)
{
ret.type1 = MSG_GAME;
ret.type2 = MSG_GAME_OPERATION;
while(game_host[now_roomnum].Ready(now_playernum) == true)
{
;
}
//cout<<"Entered from "<<now_playernum<<endl;
game_host[now_roomnum].SetMessage(now_playernum, recv_msg->msg);
game_host[now_roomnum].SetReady(now_playernum, true);
game_host[now_roomnum].SetUsed(now_playernum, false);
while(true)
{
bool tmp = game_host[now_roomnum].AllReady();
if(tmp == true)
break;
}
//cout<<"AllReady from"<<now_playernum<<endl;
string all_msg = game_host[now_roomnum].GetAllMessage();
game_host[now_roomnum].SetUsed(now_playernum, true);
while(!game_host[now_roomnum].AllUsed())
{
;
}
//cout<<"AllUsed from "<<now_playernum<<endl;
EnterCriticalSection(&cs);
game_host[now_roomnum].ClearReady();
LeaveCriticalSection(&cs);
strcpy_s(ret.msg, all_msg.c_str());
//cout<<"Return msg "<<now_playernum<<": "<<ret.msg<<endl;
}
return ret;
Now, the problem is: on a PC, when all cout are commented like above, the game freezes at once; but when I cancel the comments, the server works well.
What's more, when I run the server on my laptop, everything goes fine, no matter whether I comment the cout or not. The main difference between my laptop and PC is that my laptop's OS is Windows 8.1, while the PC is Windows 7.
I'm totally confused. It will be of great help if someone can tell me what to do. Thank you!
Looks like a multithreading issue.
By the way I see you use a Critical section around ClearReady but not when testing for AllReady. That call should be wrapped as well (or, better, write a LockedAllReady that makes use of the lock).
//cout<<"Return msg "<<now_playernum<<": "<<ret.msg<<endl;
What you mean by ret.msg? if msg is method you must do ret.msg(); , is it a field?
If you have this good then like they say above probably a timing problem, try to do cout without ret.msg and see what will happen, and then you know from where the problem is.
Related
I'm currently working on writing a reparenting window manager using C++ and the XCB library. I unmanage windows when I recieve an UnmapNotify event; in this case the code is very simple:
if (unmap_ignore > 0) {
unmap_ignore--;
return;
}
client *cl = nullptr;
size_t idx = 0;
for (client &c : clients) {
if (c.window == ev->window) {
cl = &c;
break;
}
idx++;
}
if (!cl)
return;
xcb_unmap_window(conn, cl->frame);
clients.erase(clients.begin() + idx);
However, this does not work for some clients that don't bother unmapping the window (usually happens when you force kill the process). Then instead a DestroyNotify is sent. However the ev->window field there (typeof ev = xcb_destroy_notify_event_t) is some value that isn't what I want... here are some example logs (also note each line is a new DestroyNotify event, I get it twice for some reason and each time the #window field is different but not correct):
Found a client window: 4194307 but this was destroyed: 4194305
Found a client window: 4194307 but this was destroyed: 4194313
I remember before I tried to write a window manager in Xlib and had this exact same issue. I must be missing something obvious though, but if I look at the code of other reparenting window managers like Awesome or Herbsluftwm they just use the window field and have no problems. What am I doing wrong?
(my full code is here: http://ix.io/3yDj)
One thing I suspect is that it is just giving me two children windows of the destroyed parent instead of sending the actual parent. no idea why, but it is the most logical thing I can come up with. I just want to be able to handle this so I can unmap the frame for things that don't send UnmapNotify events.
I also first thought that it may report DestroyNotify on the parent window instead of the client reparented one, so I tried checking the frame but to no avail:
Found a client window: 2097152 but this was destroyed: 4194305
Found a client window: 2097152 but this was destroyed: 4194313
I've been truly stumped on this so any help is appreciated, thanks!
Awesome for example does the exact same thing as I tried with ev->window:
static void
event_handle_destroynotify(xcb_destroy_notify_event_t *ev)
{
client_t *c;
if((c = client_getbywin(ev->window)))
client_unmanage(c, CLIENT_UNMANAGE_DESTROYED);
else
for(int i = 0; i < globalconf.embedded.len; i++)
if(globalconf.embedded.tab[i].win == ev->window)
{
xembed_window_array_take(&globalconf.embedded, i);
luaA_systray_invalidate();
}
}
I am programming for one of my project "Auction". I put all the conditions for login at both server and client side. My program runs better till some statements but in meanwhile server stops responding.
I research over that by putting print statements and over internet and I found that it is sync problem rather than coding. May be the reason would be different i am not sure.
I also want to mention that when I put "read()" on while condition, things are running as expected. Can anyone please tell me that how to remove/avoid this sync problem (may be something else rather than sync)?
Server.cpp (only some part which is running well)
while(((n = read(sockfd,buffer,4096))!=0)&&(l==false)) {
if(i==0) cout<<"Username:"<<buffer;
if(i==1) { l = true; cout<<"Password:"<<buffer; }
i++;
}
Server.cpp (part before modification that was stucked at i=1)
for(i=0; i<2; i++) { cout<<endl<<"i="<<i<<endl;
bzero(&buffer, sizeof(buffer));
if((n = read(sockfd,buffer,4096))==0) { cout<<"problem";
close(sockfd);
FD_CLR(sockfd, &allset);
client[i] = -1;
} else { cout<<buffer<<i<<endl; if(i==1) {cout<<"copied password"; }
if(i == 0) { cout<<"copied user";} }
I'm creating a webrtc-based voip app for windows in C++. I'm trying to initialize a peerconnection. I'm stuck at the part to fetch a camera. I'm using the following code to find a camera to start streaming media from (copied from the peerconnection client example):
rtc::scoped_ptr<cricket::DeviceManagerInterface> dev_manager(cricket::DeviceManagerFactory::Create());
if (!dev_manager->Init()) {
LOG(LS_ERROR) << "Can't create device manager";
return NULL;
}
std::vector<cricket::Device> devs;
if (!dev_manager->GetVideoCaptureDevices(&devs)) {
LOG(LS_ERROR) << "Can't enumerate video devices";
return NULL;
}
std::vector<cricket::Device>::iterator dev_it = devs.begin();
cricket::VideoCapturer* capturer = NULL;
for (; dev_it != devs.end(); ++dev_it) {
capturer = dev_manager->CreateVideoCapturer(*dev_it);
if (capturer != NULL)
break;
}
capturer is empty after this procedure. I stepped through the code to see what was wrong. dev_manager is succesfully intialized, devs gets a single entry (my webcam) with a name:
"logitech HD webcam c270"
And an id:
"\\\\?\\usb#vid_046d&pid_0825&mi_00#7&2dbd1a82&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}"
But after the CreateVideoCapturer() call, capturer is still empty. I get a warning in the console saying:
Warning(webrtcvideocapturer.cc:175): Failed to find capturer for id: \\?\usb#vid_046d&pid_0825&mi_00#7&2dbd1a82&1&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\{bbefb6c7-2fc4-4139-bb8b-a58bba724083}
I checked if the id I get in devs and this one match and they do. The entire log for my app can be found in this pastebin. As you can see, right after trying to assign the camera as capturer and failing, the app crashes on an assert(capturer != NULL) call somewhere in videosource.cc.
The camera is not in use, nor is it defect. The peerconnection client example works perfectly and uses the same code. I think I'm missing some step in the initialization of webrtc, but I can't find which step.
edit with additional info
I'm debug stepping through the library now. In webrtcvideocapturer.cc around line 160 is the following code:
int num_cams = info->NumberOfDevices();
char vcm_id[256] = "";
bool found = false;
for (int index = 0; index < num_cams; ++index) {
char vcm_name[256];
int32 i = info->GetDeviceName(index, vcm_name, ARRAY_SIZE(vcm_name), vcm_id, ARRAY_SIZE(vcm_id));
if (i != -1) {
if (device.name == reinterpret_cast<char*>(vcm_name)) {
found = true;
break;
}
}
}
if (!found) {
LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id;
factory_->DestroyDeviceInfo(info);
return false;
}
There are two problems with this part. First of all, if I step into info->NumberOfDevices() it shows me that that function's only content is the line return 0;. I tried hard-coding 1 there, to at least get into the for loop. Then when I step into the info->GetDeviceName() call it shows me that the content of that function is return -1;.
These two functions are meant to be implemented by a class that inherits from webrtc::VideoCaptureModule::DeviceInfo, so there is clearly something not initialized that does needs to be initialized. What do I still need to do before trying to get a camera?
What libraries did you link?
Because Google WebRTC source codes are changing rapidly, it is difficult to track down issues to the source level.
But I remember the almost same problem occurred when I accidentally linked external capture module library (video_capture_module_impl ??) or (I'm not sure) omitted internal impl (video_capture_module_internal_impl ??).
I'm trying to set up some test software for code that is already written (that I cannot change). The issue I'm having is that it is getting hung up on certain calls, so I want to try to implement something that will kill the process if it does not complete in x seconds.
The two methods I've tried to solve this problem were to use fork or pthread, both haven't worked for me so far though. I'm not sure why pthread didn't work, I'm assuming it's because the static call I used to set up the thread had some issues with the memory needed to run the function I was calling (I continually got a segfault while the function I was testing was running). Fork worked initially, but on the second time I would fork a process, it wouldn't be able to check to see if the child had finished or not.
In terms of semi-pseudo code, this is what I've written
test_runner()
{
bool result;
testClass* myTestClass = new testClass();
pid_t pID = fork();
if(pID == 0) //Child
{
myTestClass->test_function(); //function in question being tested
}
else if(pID > 0) //Parent
{
int status;
sleep(5);
if(waitpid(0,&status,WNOHANG) == 0)
{
kill(pID,SIGKILL); //If child hasn't finished, kill process and fail test
result = false;
}
else
result = true;
}
}
This method worked for the initial test, but then when I would go to test a second function, the if(waitpid(0,&status,WNOHANG) == 0) would return that the child had finished, even when it had not.
The pthread method looked along these lines
bool result;
test_runner()
{
long thread = 1;
pthread_t* thread_handle = (pthread_t*) malloc (sizeof(pthread_t));
pthread_create(&thread_handle[thread], NULL, &funcTest, (void *)&thread); //Begin class that tests function in question
sleep(10);
if(pthread_cancel(thread_handle[thread] == 0))
//Child process got stuck, deal with accordingly
else
//Child process did not get stuck, deal with accordingly
}
static void* funcTest(void*)
{
result = false;
testClass* myTestClass = new testClass();
result = myTestClass->test_function();
}
Obviously there is a little more going on than what I've shown, I just wanted to put the general idea down. I guess what I'm looking for is if there is a better way to go about handling a problem like this, or maybe if someone sees any blatant issues with what I'm trying to do (I'm relatively new to C++). Like I mentioned, I'm not allowed to go into the code that I'm setting up the test software for, which prevents me from putting signal handlers in the function I'm testing. I can only call the function, and then deal with it from there.
If c++11 is legit you could utilize future with wait_for for this purpose.
For example (live demo):
std::future<int> future = std::async(std::launch::async, [](){
std::this_thread::sleep_for(std::chrono::seconds(3));
return 8;
});
std::future_status status = future.wait_for(std::chrono::seconds(5));
if (status == std::future_status::timeout) {
std::cout << "Timeout" <<endl ;
} else{
cout << "Success" <<endl ;
} // will print Success
std::future<int> future2 = std::async(std::launch::async, [](){
std::this_thread::sleep_for(std::chrono::seconds(3));
return 8;
});
std::future_status status2 = future2.wait_for(std::chrono::seconds(1));
if (status2 == std::future_status::timeout) {
std::cout << "Timeout" <<endl ;
} else{
cout << "Success" <<endl ;
} // will print Timeout
Another thing:
As per the documentation using waitpid with 0 :
meaning wait for any child process whose process group ID is equal to
that of the calling process.
Avoid using pthread_cancel it's probably not a good idea.
I think I am making a simple mistake, but since I noticed there are many boost experts here, I thought I would ask for help.
I am trying to use boost threads(1_40) on windows xp. The main program loads a dll, starts the thread like so (note this is not in a class, the static does not mean static to a class but private to the file).
static boost::thread network_thread;
static bool quit = false;
HANDLE quitEvent;
//some code omitted for clarity, ask if you think it would help
void network_start()
{
HANDLE *waitHandles = (HANDLE*)malloc(3 * sizeof(HANDLE));
waitHandles[0] = quitEvent;
waitHandles[1] = recvEvent;
waitHandles[2] = pendingEvent;
do {
//read network stuff, or quit event
dwEvents =WaitForMultipleObjects(3, waitHandles, FALSE, timeout);
} while (!quit)
}
DllClass::InitInstance()
{
}
DllClass::ExportedFunction()
{
network_thread = boost::thread(boost::bind<void>(network_start));
}
DllClass::ExitInstance()
{
//signal quit (which works)
quit = true;
SetEvent(QuitEvent);
//the following code is slightly verbose because I'm trying to figure out what's wrong
try {
if (network_thread.joinable() ) {
network_thread.join();
} else {
TRACE("Too late!");
}
} catch (boost::thread_interrupted&) {
TRACE("NET INTERRUPTED");
}
}
The problem is that the main thread is hanging on the join, and the network thread is hanging at the end of _endthreadex. What am I misunderstanding?
You are not supposed to create/end threads in InitInstance/ExitInstance,
see http://support.microsoft.com/default.aspx?scid=kb;EN-US;142243 for more info. Also, see http://msdn.microsoft.com/en-us/library/ms682583%28VS.85%29.aspx about DllMain in general.