I have a question regarding Win32 API process treatment.
I have two processes. Process 1, before starting, must run process 2, which waits for the same resource as process 1. It is a .txt file with some integer values. It means that Process1 should be started FIRST and run Process2. The Process1 MUST be completed after Process2.
It should work as followig:
1.Process1 is created.
2.Process 1 is blocked.
3.Process 2 is created and excecuted.
4.Process 1 is unlocked and executed.
5.Process 2 ends.
6.Process 1 ends.
I searched here for a question similar to mine, I've found only the link below, where a SpinLock class is presented:
C++11 Implementation of Spinlock using <atomic>
The issue is to implement it correctly, I've deleted my incorrect implementations of SpinLock methods from main() function.
It was almost impossible to find any example of using this method in practice, hence I am asking this question to have a look on it:
#include <iostream>
#include <Windows.h>
#include <string>
#include <tchar.h>
#include <cstdlib>
#include <pthread.h>
#include <atomic>
using namespace std;
class SpinLock {
atomic_flag locked = ATOMIC_FLAG_INIT ;
public:
void lock() {
while (locked.test_and_set(memory_order_acquire)) { ; }
}
void unlock() {
locked.clear(memory_order_release);
}
};
int main( int argc, TCHAR *argv[] )
{
//process 1 generates N random values between 1 and 100,then saves it to txt file i argv[1] stores quanity of values, which will be saved to file
STARTUPINFO si = {};
si.cb = sizeof si;
SpinLock SpinLockVar;
PROCESS_INFORMATION pi = {};
const TCHAR* target1 = _T("C:\\USERS\\Admin\\Documents\\File1.exe"); //process 1
const TCHAR* target2 = _T("C:\\USERS\\Admin\\Documents\\File2.exe");
//Process 1 , before starting generating values and saving them to file, runs Process2,which is awaiting for access to txt file (SPINLOCK ).
//Process 1 is terminating after finishing Process 2
if ( !CreateProcess(target1,GetCommandLine(), 0, FALSE, 0, 0, 0, 0, &si, &pi) )
{
cerr << "CreateProcess failed (" << GetLastError() << ").\n";
}
else
{
WaitForSingleObject(pi.hProcess, INFINITE);
if ( PostThreadMessage(pi.dwThreadId, WM_QUIT, 0, 0) ) // Good
cout << "Request to terminate process has been sent!";
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
if ( !CreateProcess(target2,0, 0, FALSE, 0, 0, 0, 0, &si, &pi) )
{
cerr << "CreateProcess failed (" << GetLastError() << ").\n";
}
else
{
WaitForSingleObject(pi.hProcess, INFINITE);
/*
if ( TerminateProcess(pi.hProcess, 0) ) // Evil
cout << "Process terminated!";
*/
if ( PostThreadMessage(pi.dwThreadId, WM_QUIT, 0, 0) ) // Good
cout << "Request to terminate process has been sent!";
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
cin.sync();
cin.ignore();
return 0;
}
UPDATE
I have used mutex function for now, and it works partially - it has a mutex "spinlock" mechanism, although it sometimes displaying very strange. I have randomly the result which I expect and which is generating randomly after running my program - the first line in cmd is from thread which runs process2, the second line is result of process1
Please check my code :
#include <windows.h>
#include <stdio.h>
#include <pthread.h>
#include <tchar.h>
#include <mutex>
#include <iostream>
HANDLE hMutex;
DWORD ThreadProc1(LPVOID* arg)
{
const TCHAR* target = _T("C:\\USERS\\Admin\\Documents\\File2.exe");
PROCESS_INFORMATION pInfo;
STARTUPINFO sInfo = { sizeof(pInfo) };
BOOL res = CreateProcess(target, 0, 0, FALSE, 0, 0, 0, 0, &sInfo, &pInfo); //process2
if (!res) return 1;
WaitForSingleObject(pInfo.hThread, INFINITE);
CloseHandle(pInfo.hThread);
CloseHandle(pInfo.hProcess);
return TRUE;
}
int main(void)
{
PROCESS_INFORMATION pInfo;
STARTUPINFO sInfo = { sizeof(pInfo) };
const TCHAR* target = _T("C:\\USERS\\Admin\\Documents\\File1.exe");
HANDLE hThreads;
DWORD threadID1;
hMutex=CreateMutex(NULL, FALSE, NULL); //create mutex(resources=1)
WaitForSingleObject(hMutex, INFINITE); //process2 call WaitForSingleObject(hmutex) first to get mutex
hThreads=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, &hMutex, 0, &threadID1);
WaitForSingleObject(hMutex,INFINITE);//process1 call WaitForSingleObject(hmutex) and block
BOOL res = CreateProcess(target, GetCommandLine(), 0, FALSE, 0, 0, 0, 0, &sInfo, &pInfo);//process1
if (!res) return 1;
ReleaseMutex(hMutex);// process2 do file operations, and then release mutex
WaitForSingleObject(hMutex,INFINITE);// process1 WaitForSingleObject(hmutex) unblock(resources -1),
ReleaseMutex(hMutex); // then release mutex(resources +1)
CloseHandle(hMutex);
WaitForSingleObject(hThreads,INFINITE);
CloseHandle(hThreads); //process 1 closing thread after process 2 ends
CloseHandle(pInfo.hProcess);
CloseHandle(pInfo.hThread);
return 0;
}
First, I think you don't need to use mutex or Spinlock. You could create process1 with CREATE_SUSPENDED, create process2, wait for process2 to exit, then call ResumeThread(pi1.hThread) although there may be differences in step 4 and 5.
#include <windows.h>
#include <string>
#include <tchar.h>
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int argc, TCHAR* argv[])
{
STARTUPINFO si1 = { 0 }, si2 = { 0 };
si1.cb = sizeof si1;
si2.cb = sizeof si2;
PROCESS_INFORMATION pi1 = { 0 }, pi2 = { 0 };
const TCHAR* target1 = _T("C:\\Users\\drakew\\source\\repos\\Project4\\Debug\\Project4.exe");
const TCHAR* target2 = _T("C:\\Users\\drakew\\source\\repos\\Project6\\Debug\\Project6.exe");
if (!CreateProcess(target1, 0, 0, FALSE, 0, CREATE_SUSPENDED, 0, 0, &si1, &pi1))
{
cerr << "CreateProcess failed (" << GetLastError() << ").\n";
}
else
{
printf("Process1 is created ...\n");
printf("Process1 is blocked ...\n");
if (!CreateProcess(target2, 0, 0, FALSE, 0, 0, 0, 0, &si2, &pi2))//Process 2 is created and excecuted ...
{
cerr << "CreateProcess failed (" << GetLastError() << ").\n";
}
else
{
WaitForSingleObject(pi2.hProcess, INFINITE);
printf("Process 2 ends ...\n");
CloseHandle(pi2.hProcess);
CloseHandle(pi2.hThread);
}
ResumeThread(pi1.hThread); //Process 1 is unlocked and executed ...
WaitForSingleObject(pi1.hProcess, INFINITE);
printf("Process 1 ends ...\n");
CloseHandle(pi1.hProcess);
CloseHandle(pi1.hThread);
}
cin.sync();
cin.ignore();
return 0;
}
Then, If you want to block at the specific location of process1, then you have to modify process1 and process2 to keep synchronization.
I use event to implement lock.
Process1:
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
HANDLE hEvent1 = OpenEvent(EVENT_MODIFY_STATE| SYNCHRONIZE, FALSE, L"Global\\MyEvent1");
HANDLE hEvent2 = OpenEvent(EVENT_MODIFY_STATE| SYNCHRONIZE, FALSE, L"Global\\MyEvent2");
printf("process1: step1 ...\n");
SetEvent(hEvent1);
printf("process1: step2 ...\n");
DWORD dwWaitResult = WaitForSingleObject(hEvent2, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
printf("process1: step4 ...\n");
break;
default:
return FALSE;
}
CloseHandle(hEvent1);
CloseHandle(hEvent2);
}
Process2:
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
HANDLE hEvent1 = OpenEvent(EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, L"Global\\MyEvent1");
HANDLE hEvent2 = OpenEvent(EVENT_MODIFY_STATE | SYNCHRONIZE, FALSE, L"Global\\MyEvent2");
DWORD dwWaitResult = WaitForSingleObject(hEvent1, INFINITE);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
printf("process2: step3 ...\n");
SetEvent(hEvent2);
break;
default:
return FALSE;
}
CloseHandle(hEvent1);
CloseHandle(hEvent2);
return 1;
}
Main Process:
#include <windows.h>
#include <string>
#include <tchar.h>
#include <cstdlib>
#include <mutex>
#include <iostream>
using namespace std;
int main(int argc, TCHAR* argv[])
{
STARTUPINFO si1 = { 0 }, si2 = { 0 };
si1.cb = sizeof si1;
si2.cb = sizeof si2;
PROCESS_INFORMATION pi1 = { 0 }, pi2 = { 0 };
mutex mtx;
HANDLE hEvent1 = CreateEvent(NULL, FALSE, FALSE, L"Global\\MyEvent1");
HANDLE hEvent2 = CreateEvent(NULL, FALSE, FALSE, L"Global\\MyEvent2");
const TCHAR* target1 = _T("C:\\path\\process1.exe");
const TCHAR* target2 = _T("C:\\path\\process2.exe");
if (!CreateProcess(target1, 0, 0, FALSE, 0, 0, 0, 0, &si1, &pi1))
{
cerr << "CreateProcess failed (" << GetLastError() << ").\n";
}
else
{
if (!CreateProcess(target2, 0, 0, FALSE, 0, 0, 0, 0, &si2, &pi2))
{
cerr << "CreateProcess failed (" << GetLastError() << ").\n";
}
else
{
WaitForSingleObject(pi2.hProcess, INFINITE);
printf("process2: step5 ...\n");
CloseHandle(pi2.hProcess);
CloseHandle(pi2.hThread);
}
WaitForSingleObject(pi1.hProcess, INFINITE);
printf("process1: step6 ...\n");
CloseHandle(pi1.hProcess);
CloseHandle(pi1.hThread);
}
CloseHandle(hEvent1);
CloseHandle(hEvent2);
cin.sync();
cin.ignore();
return 0;
}
Result:
Related
In Win32 C++, How to WaitForSingleObject and Detect Ctrl-C at the same time?
I tried the following console application by compiling it in the Code::Blocks C++ compiler for windows.
Then, I tried pressing Control-C many times while running... it basically doesn't call the control-c handler while the main thread is in "WaitForSingleObject".
Is there a way to fix this?
Eventually, I want my Control-C handler to kill the secondary thread using TerminateThread and return control to mainthread breaking WaitForSingleObject... But, because of the wait the second thread is written i can't change any of the code...
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <atomic>
using namespace std;
BOOL WINAPI fun1(DWORD id);
DWORD WINAPI fun2(void*);
atomic<DWORD> threadid {0};
int main()
{
DWORD threadid1;
cout << "Hello world!" << endl;
SetConsoleCtrlHandler(fun1, TRUE);
HANDLE H1 = CreateThread(NULL, 0, fun2, 0, 0, &threadid1);
threadid = threadid1;
WaitForSingleObject(H1, INFINITE);
return 0;
}
BOOL WINAPI fun1(DWORD id)
{
Beep(750, 300);
printf("CtrlHandler:(%ld)\n", id);
if (threadid != 0) {
HANDLE H2 = OpenThread(THREAD_TERMINATE, FALSE, threadid);
if (H2) {
//TerminateThread(H2, 0);
//threadid = 0;
CloseHandle(H2);
}
}
return TRUE;
}
DWORD WINAPI fun2(void*)
{
// This thread will eventually do some work...
// and I don't want to rewrite this code...
// to check for a flag from another thread...
int count = 0;
while(1) {
printf("count: %d\n", count);
Sleep(1000);
}
return 0;
}
A SetConsoleCtrlHandler() handler gets run by the OS in its own thread. This is stated as much in the documentation:
https://learn.microsoft.com/en-us/windows/console/handlerroutine
An application-defined function used with the SetConsoleCtrlHandler function. A console process uses this function to handle control signals received by the process. When the signal is received, the system creates a new thread in the process to execute the function.
You need to have that signal thread notify your worker thread to terminate itself, you can't (safely) just terminate the thread directly (ie, DO NOT use TerminateThread()).
Try this:
#include <windows.h>
#include <cstdio>
#include <iostream>
#include <atomic>
using namespace std;
BOOL WINAPI fun1(DWORD);
DWORD WINAPI fun2(void*);
atomic<bool> exitThread {false};
int main()
{
cout << "Hello world!" << endl;
SetConsoleCtrlHandler(fun1, TRUE);
HANDLE H1 = CreateThread(NULL, 0, fun2, 0, 0, NULL);
if (H1)
{
WaitForSingleObject(H1, INFINITE);
CloseHandle(H1);
}
return 0;
}
BOOL WINAPI fun1(DWORD id)
{
Beep(750, 300);
printf("CtrlHandler:(%lu)\n", id);
exitThread = true;
return TRUE;
}
DWORD WINAPI fun2(void*)
{
// This thread will eventually do some work...
int count = 0;
while (!static_cast<bool>(exitThread)) {
printf("count: %d\n", count++);
Sleep(1000);
}
return 0;
}
However, do note that creating a thread just to wait on it is a waste of a thread. You may as well just do your work in main() directly instead, eg:
#include <windows.h>
#include <cstdio>
#include <iostream>
#include <atomic>
using namespace std;
BOOL WINAPI fun1(DWORD);
atomic<bool> exitApp {false};
int main()
{
cout << "Hello world!" << endl;
SetConsoleCtrlHandler(fun1, TRUE);
// This will eventually do some work...
int count = 0;
while (!static_cast<bool>(exitApp)) {
printf("count: %d\n", count++);
Sleep(1000);
}
return 0;
}
BOOL WINAPI fun1(DWORD id)
{
Beep(750, 300);
printf("CtrlHandler:(%lu)\n", id);
exitApp = true;
return TRUE;
}
I cleaned up your code slightly and it seems like the Ctrl+C handler is running when expected (even though it doesn't do anything particularly useful). When I type Ctrl+C, I see that fun1 can run multiple times while the main thread is running WaitForSingleObject.
Your original code for fun1 was beeping before printing, and it wasn't flushing the stdout buffer, so maybe you thought the code wasn't actually running or that it was getting delayed.
Note that I am just answering questions you asked about detecting Ctrl+C while waiting for an object; I'm not attempting to help you do anything useful in your Ctrl+C handler.
Here is the cleaned-up version of your code that I used for testing:
#include <windows.h>
#include <stdio.h>
#include <atomic>
std::atomic<DWORD> threadid {0};
BOOL WINAPI fun1(DWORD id) {
printf("fun1: %ld\n", id);
fflush(stdout);
Beep(750, 100);
// This doesn't do anything useful; can be removed.
if (threadid != 0) {
HANDLE H2 = OpenThread(THREAD_TERMINATE, FALSE, threadid);
if (H2) { CloseHandle(H2); }
}
return 1;
}
DWORD WINAPI fun2(void *) {
unsigned int count = 0;
while(1) {
count++;
printf("count: %d\n", count);
fflush(stdout);
Sleep(4000);
}
return 0;
}
int main() {
printf("Hello world!\n");
fflush(stdout);
SetConsoleCtrlHandler(fun1, TRUE);
DWORD threadid1;
HANDLE H1 = CreateThread(NULL, 0, fun2, 0, 0, &threadid1);
threadid = threadid1;
printf("Waiting for single oblect.\n");
fflush(stdout);
WaitForSingleObject(H1, INFINITE);
printf("Done waiting for single oblect.\n");
fflush(stdout);
return 0;
}
Example output:
Hello world!
Waiting for single oblect.
count: 1
count: 2
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
fun1: 0
count: 3
count: 4
I compiled the code in MSYS2, targeting 64-bit Windows, with this command:
g++ -std=gnu++20 -Wall -Wextra test.cpp
When I execute system in a thread, nothing happens. Is there a solution?
#include <iostream>
#include <Windows.h>
using namespace std;
void runffplay()
{
const char* _cmd = "ffplay -fs -loop 0 \"D:\\dynamic wallpaper\\1.mp4\"";
system(_cmd);
}
CloseHandle(CreateThread(0, 0, (PTHREAD_START_ROUTINE)runffplay, 0, 0, 0));
Your runffplay() function has the wrong signature, so you are going to end up corrupting the thread's call stack. Read the CreateThread() and ThreadProc documentations.
Also, you are not doing any error handling.
Try something more like this instead:
#include <iostream>
#include <cstdlib>
#include <Windows.h>
DWORD WINAPI runffplay(LPVOID)
{
// instead of system(), consider using exec..(), or CreateProcess() directly...
const char* _cmd = "ffplay -fs -loop 0 \"D:\\dynamic wallpaper\\1.mp4\"";
int ret = std::system(_cmd);
std::cout << "system() returned " << ret << std::endl;
return 0;
}
HANDLE hThread = CreateThread(NULL, 0, runffplay, NULL, 0, NULL);
if (!hThread) {
DWORD err = GetLastError();
std::cerr << "CreateThread() failed with error " << err << std::endl;
}
else {
...
CloseHandle(hThread);
}
Otherwise, use std::thread instead of CreateThread() directly:
#include <iostream>
#include <thread>
#include <cstdlib>
void runffplay()
{
// instead of system(), consider using exec..(), or CreateProcess() directly...
const char* _cmd = "ffplay -fs -loop 0 \"D:\\dynamic wallpaper\\1.mp4\"";
int ret = std::system(_cmd);
std::cout << "system() returned " << ret << std::endl;
}
std::thread thrd;
try {
thrd = std::thread(runffplay);
}
catch (const std::system_error &e) {
std::cerr << "thread failed with error " << e << std::endl;
}
...
if (thrd.joinable()) {
thrd.join();
}
Use CreateProcess to get the expected result
#include <iostream>
#include <Windows.h>
using namespace std;
HWND ffplayw = 0;
void SetWallpaper()
{
while (ffplayw == 0)
{
ffplayw = FindWindowW(L"SDL_app", 0);
Sleep(10);
}
}
int main()
{
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
if (CreateProcess(L"D:\\my-tools\\ffmpeg\\bin\\ffplay.exe",
(LPWSTR)L" -fs -loop 0 \"D:\\dynamic wallpaper\\1.mp4\"",
0, 0, 0, 0, 0, 0, &info, &processInfo))
{
// WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
Sleep(500);
SetWallpaper();
}
return 0;
}
this is okay too:
CreateProcess(
L"C:\\Windows\\System32\\cmd.exe",
(LPWSTR)L" /c ffplay -loop 0 \"D:\\dynamic wallpaper\\1.mp4\"",
0, 0, 0, 0, 0, 0, &info, &processInfo)
I wrote a simple example of using a semaphore, but sometimes messages from the first thread are not displayed. What the problem?
#include <iostream>
#include <windows.h>
#include <process.h>
HANDLE Semaphore;
void test1(void*) {
WaitForSingleObject(Semaphore, INFINITE);
std::cout << "Thread1: access granted";
_endthread();
}
void test2(void*) {
ReleaseSemaphore(Semaphore, 1, NULL);
_endthread();
}
int main() {
Semaphore = CreateSemaphore(NULL, 0, 1, NULL);
_beginthread(test1, 2048, NULL);
_beginthread(test2, 2048, NULL);
CloseHandle(Semaphore);
}
In windows 10, if i create a process to open calc.exe first its trigger calc.exe and exit that process after that it opens calculator.exe. How can i get actual process id that shows in task manager.
i am using following code to create the process and display process id
if(!CreateProcess(("C:\\WINDOWS\\system32\\calc.exe"),
NULL,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&startup_info,
&pi) )
{
args.GetReturnValue().Set(Nan::New(response).ToLocalChecked());
}
else
{
int dwPid = GetProcessId(pi.hProcess);
int v = dwPid->Int32Value();
args.GetReturnValue().Set(dwPid);
}
#include <iostream>
#include <vector>
#include <cstring>
#include <windows.h>
#include <tlhelp32.h>
using std::vector;
using std::cout;
using std::endl;
vector<DWORD> pids_from_ppid(DWORD ppid) {
vector<DWORD> pids;
HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hp, &pe)) {
do {
if (pe.th32ParentProcessID == ppid) {
pids.push_back(pe.th32ProcessID);
}
} while (Process32Next(hp, &pe));
}
CloseHandle(hp);
return pids;
}
int main(int argc,char *argv[]) {
if (arc >= 2) {
DWORD ppid = (DWORD)strtoul(argv[1], nullptr, 10);
vector<DWORD> pidVec = pids_from_ppid(ppid);
for (int i = 0; i < pidVec.size(); i++) {
cout << pidVec[i] << endl;
}
}
return 0;
}
I'm trying to make a simple client-server program using windows file mapping and that uses semaphores. The clients send to the server 2 numbers, the server computes nr1+nr2 and nr1 * nr2. I tried something but it doesn't even work for 1 client and I want it to work for more clients. Here's the code:
the server:
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct {
int nr1;
int nr2;
} Mesaj;
int main(int argc, char** argv) {
Mesaj* mesaj;
HANDLE createSemaphore = CreateSemaphore(NULL, 1, 1, "Semafor");
if (createSemaphore == NULL || createSemaphore == INVALID_HANDLE_VALUE) {
wcout << "Failed to create a semaphore\n";
} else {
wcout << "Created the semaphore\n";
}
HANDLE hMemory = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, sizeof(Mesaj), "SharedMemory");
WaitForSingleObject(createSemaphore, INFINITE);
mesaj = (Mesaj*) MapViewOfFile(hMemory, FILE_MAP_READ, 0, 0, sizeof(Mesaj));
printf("The numbers received are: %d, %d\n", mesaj->nr1, mesaj->nr2);
int produs = mesaj->nr1 * mesaj->nr2;
int suma = mesaj->nr1 + mesaj->nr2;
printf("\nSuma numerelor este: %d iar produsul lor este: %d", suma, produs);
ReleaseSemaphore(createSemaphore, 1, NULL);
Sleep(INFINITE);
return 0;
}
the client:
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct {
int nr1;
int nr2;
} Mesaj;
int main(int argc, char** argv) {
Mesaj* mesaj, *mesaj2;
mesaj2 = (Mesaj*) malloc(sizeof(Mesaj));
HANDLE hMemory = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE,
"SharedMemory");
if (hMemory == NULL) {
wcout << "Error at OpenFileMapping\n";
}
HANDLE openSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS,TRUE,"Semafor");
if(openSemaphore != NULL || openSemaphore != INVALID_HANDLE_VALUE){
wcout<<"the semaphore is opened\n";
}
mesaj2 = (Mesaj*) MapViewOfFile(hMemory, FILE_MAP_WRITE, 0, 0,
sizeof(Mesaj));
int nr1 = 0, nr2 = 0;
printf("Give a number: ");
scanf("%d", &nr1);
printf("Give another number: ");
scanf("%d", &nr2);
mesaj2->nr1 = nr1;
mesaj2->nr2 = nr2;
if (mesaj2 == NULL) {
wcout << "Error\n"
} else {
wcout << "I sent " << mesaj2->nr1 << " and " << mesaj2->nr2 << endl;
}
system("pause");
return 0;
}
What exactly am I doing wrong? How should I work with semaphores?
When I open the server it doesn't wait for the client.
The documentation for CreateSemaphore says
The state of a semaphore object is signaled when its count is greater than zero, and nonsignaled when its count is equal to zero. The lInitialCount parameter specifies the initial count.
You passed lInitialCount=1 when you created the semaphore. and 1 > 0, so the semaphore is signaled and the WaitForSingleObject returns immediately.
You presumably want to create the semaphore with an initial count of 0, so that it does not become signaled until somebody calls ReleaseSemaphore.