pthreads fill buffer in unexpected way - c

I am trying to fill a buffer using pthreads in a simple TCP/IP server client communication.
ATTENTION: Client writes its contents to an external server-address (not mine) and server reads its contents from an external client. The client and server that I have put below, do not communicate with each other.
The buffer is filled in two ways:
Server reads a message and puts it into the buffer
Client creates a message and puts it into the buffer
Here is the client function:
void *client(void *threadid)
{
//CLIENT INITIALIZATION AND CONNECT TO SERVER PROPERLY
//sleep(1); //sleep 1 second before you send again
char *buff = "message1"; //message1,2,3 etc is defined by a random function
pthread_mutex_lock(&lock);
write(sockfd, buff, strlen(buff)+1);
buffer_fill(buff);
pthread_mutex_unlock(&lock);
}
pthread_exit(NULL);
}
And here is the server function. Server reads from an external device that runs the same client code with me:
void *server(void *threadid)
{
//SERVER INITIALIZATION USING THE PROPER PORT AND ADDRESS
pthread_mutex_lock(&lock);
bzero(buff, MAX_LENGTH);
// read the message from client and copy it in buffer
while(strlen(buff) == 0){
read(sockfd, buff, sizeof(buff));
}
buffer_fill(buff);
pthread_mutex_unlock(&lock);
}
pthread_exit(NULL);
}
I am using a simple pthread initialization in my main function. So I am calling each function through the utilization of a thread:
int main(int argc, char **argv)
{
pthread_t threads[NUM_THREADS];
int rc[NUM_THREADS];
long t;
for(t=0; t<NUM_THREADS; t++){
//initiallize thread
if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("\n mutex init failed\n");
return 1;
}
//create each thread according to value of t
if(t==0){
rc[t] = pthread_create(&threads[t], NULL, server, (void *)t);
}else if(t==1){
rc[t] = pthread_create(&threads[t], NULL, client, (void *)t);
}
}
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_mutex_destroy(&lock);
/* Last thing that main() should do */
pthread_exit(NULL);
return 0;
}
I assume the problem lies somewhere in the use of the (extremely simple) buffer_fill(char *message) in combination with the threads (note : msg is a global variable initialized to zero outside main, int msg = 0):
void buffer_fill(char *m){
if (msg<=MAX_MESSAGES){
buffer[msg] = m;
msg ++;
}
print_buffer();
}
When I execute this code continuously I get that kind of result:
first print:
message2
second print:
message1
message1
third print:
message5
message5
message5
and so on.
Note that messages[1:5] are been selected randomly by the client and do not affect the outcome
I assure you that the server client set up is correct. I checked it
before writing the code that fills the buffer
Why is it that messages print like that and not in a serial form? I want every random message that is going to be written by client and every message that is read by the server to be stacked on buffer one after the other like this:
first print:
message2
second print:
message2
message1
third print:
message2
message1
message5

you problem happens here
void buffer_fill(char *m){
if (msg<=MAX_MESSAGES){
buffer[msg] = m; // where
msg ++;
}
print_buffer();
}
you should copy the value to buffer from m using strcpy or using a loop.
Edit: char * <=> const char * you should create an array or dynamically allocate the buffer.

Related

How do I write a string to a 2D array in C?

So I am working on a multi-threading program with 4 threads. For thread1 I am grabbing input from stdin and then putting it into buffer1, thread2 then reads from buffer1, modifies it, then puts it in buffer2 for thread3 to read, and so on....
After I have read from buffer1 (in my thread2 function), I have successfully altered the data, now I want to put it in buffer2, but I am getting the error of "expression must be a modifiable lvalue". Does anyone know why??
My thread 2 function is below and the error is appearing in buffer2[write2] = updatedStr;
void *line_separator_thread(void *args)
{
// Consuming from buffer 1 and producing to buffer 2
int haveStop = 0;
while (1)
{
// Snag the mutext for a read
pthread_mutex_lock(&mutex1);
// Release the mutex and block on the condition
pthread_cond_wait(&readyBuffer1, &mutex1);
// Process all unread slots from the buffer1 queue
while (buffer1[read1][0] != -1) // Look for no sentinal value
{
haveStop = haveStopInText(buffer1[read1]);
if (haveStop)
break;
// ***If no break, then read from buffer1, and modify \n to be a space?
// str_replace(orig, replace, with)
char *updatedStr = str_replace(buffer1[read1], "\n", " ");
printf("UPDATED STRING: %s\n", updatedStr);
read1 = (read1 + 1) % 5;
// ***Put the updated string in buffer 2?
pthread_mutex_lock(&mutex2);
buffer2[write2] = updatedStr; //ERROR IS HERE!!!
// ***Need to change buffer1[read1][0] So that it doesn't keep looping?
}
// ***Unlock the mutex here? Or outside of the while loop?
pthread_mutex_unlock(&mutex1);
}
return NULL;
Buffer variables and read/write variables are below
char buffer1[5][1000]; //inputThread + lineSeparatorThread
char buffer2[5][1000];
char buffer3[5][1000];
// Set up variables to let the threads know where is it safe to read from and write to
int write1 = 0;
int read1 = 0;
int write2 = 0;
int read2 = 0;
int write3 = 0;
int read3 = 0;
And lastly, below is in my main function where I am creating the 4 threads
pthread_create(&outputThread, &attr, output_thread, NULL);
usleep(100); // Force the program to allow output thread to actually come up and pend on readyBuffer 3 first
pthread_create(&plusSignThread, &attr, plus_sign_thread, NULL);
usleep(100); // Force the program to allow plus_sign_thread thread to actually come up first
pthread_create(&lineSeparatorThread, &attr, line_separator_thread, NULL);
usleep(100); // Force the program to allow line_separator_thread thread to actually come up first
pthread_create(&inputThread, &attr, input_thread, NULL);
pthread_join(inputThread, NULL);
pthread_join(lineSeparatorThread, NULL);
pthread_join(plusSignThread, NULL);
pthread_join(outputThread, NULL);

Which synchronization primitive should I employ here?

while(1) {
char message_buffer[SIZE];
ssize_t message_length = mq_receive(mq_identifier, message_buffer, _mqueue_max_msg_size NULL);
if(message_len == -1) { /* error handling... */}
pthread_t pt1;
int ret = pthread_create(&pt1, NULL, handle_message, message_buffer);
if(ret) { /* error handling ... */}
}
void * handle_message (void * message) {
puts((char *) message);
return NULL;
}
The above example is not an MRE but it is extremely simple:
I've got a main thread with a loop that constantly consumes messages from a message queue. Once a new message is received, it is stored in the local message_buffer buffer. Then, a new thread is spawned to "take care" of said new message, and thus the message buffer's address is passed into handle_message, which the new thread subsequently executes.
The problem
Often, 2 threads will print the same message, even though I can verify with a 100% certainty that the messages in the queue were not the same.
I am not completely certain, but I think I understand why this is happening:
say that I push 2 different messages to the mqueue and only then I begin consuming them.
In the first iteration of the while loop, the message will get consumed from the queue and saved to message_buffer. A new thread will get spawned and the address of message_length passed to it. But that thread may not be fast enough to print the buffer's contents to the stream before the next message gets consumed (on the next iteration of the loop), and the contents of message_buffer subsequently overridden. Thus the first and second thread now print the same value.
My question is: what is the most efficient way to solve this? I'm pretty new to parallel programming and threading/pthreads and I'm pretty overwhelmed by the different synchronization primitives.
Mutex trouble
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
while(1) {
char message_buffer[SIZE];
pthread_mutex_lock(&m);
ssize_t message_length = mq_receive(mq_identifier, message_buffer, _mqueue_max_msg_size NULL);
pthred_mutex_unlock(&m);
if(message_len == -1) { /* error handling... */}
pthread_t pt1;
int ret = pthread_create(&pt1, NULL, handle_message, message_buffer);
if(ret) { /* error handling ... */}
}
void * handle_message (void * message) {
char own_buffer[SIZE];
pthread_mutex_lock(&m);
strncpy(own_buffer, (char *) message, SIZE);
pthread_mutex_unlock(&m);
puts(own_buffer);
return NULL;
}
I don't think my current mutex implementation is right as the threads are still receiving duplicate messages. The main thread can lock the mutex, consume a message into the buffer, unlock the mutex, spawn a thread, but that thread still may hang and the main one could just rewrite the buffer again (as the buffer mutex was never locked by the new thread), effectively making my current mutex implementation useless? How do I overcome this?
The problem is that you end the loop that contains message_buffer before guaranteeing that the thread has finished with that memory.
while (1) {
char message_buffer[SIZE];
ssize_t message_length = mq_receive(...);
if (message_len == -1) { /* error handling */ }
pthread_t pt1;
int ret = pthread_create(&pt1, NULL, handle_message, message_buffer);
if (ret) { /* error handling */ }
/****** Can't go beyond here until thread is done with message_buffer. ******/
}
void * handle_message (void * message) {
char own_buffer[SIZE];
strncpy(own_buffer, (char *) message, SIZE);
/******* Only now can the caller loop back. ******/
puts(own_buffer);
return NULL;
}
You could use a semaphore or similar.
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int copied = 0;
while (1) {
char message_buffer[SIZE];
ssize_t message_length = mq_receive(...);
if (message_len == -1) { /* error handling */ }
pthread_t pt1;
int ret = pthread_create(&pt1, NULL, handle_message, message_buffer);
if (ret) { /* error handling */ }
// Wait until threads is done with message_buffer.
pthread_mutex_lock(&mutex);
while (!copied) pthread_cond_wait(&cond, &mutex);
copied = 0;
pthread_mutex_unlock(&mutex);
}
void * handle_message (void * message) {
char own_buffer[SIZE];
strncpy(own_buffer, (char *) message, SIZE);
// Done with caller's buffer.
// Signal caller to continue.
pthread_mutex_lock(&mutex);
copied = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
puts(own_buffer);
return NULL;
}
(The added chunks effectively perform semaphore operations. See the last snippet of this answer for a more generic implementation.)
But there's a simpler solution: Make the copy before creating the thread.
while (1) {
char message_buffer[SIZE];
ssize_t message_length = mq_receive(...);
if (message_len == -1) { /* error handling */ }
pthread_t pt1;
int ret = pthread_create(&pt1, NULL, handle_message, strdup(message_buffer));
if (ret) { /* error handling */ }
}
void * handle_message (void * message) {
char * own_buffer = message;
puts(own_buffer);
free(own_buffer);
return NULL;
}

Asynchronous Majordomo Pattern example using the CZMQ-4.1.0 new zsock API updated not working

After installing zmq and czmq with brew, I tried to compile and play the Asynchronous-Majordomo-Pattern but it did not work as it requires czmq v3. As far as I understood, I tried to update it to the v4, using zactor because
zthread is deprecated in favor of zactor http://czmq.zeromq.org/czmq3-0:zthread
So right now the following code looks fine to me as updated async-majordomo pattern, but it does not work as expected, It does not create any thread when I run it via my terminal.
// Round-trip demonstrator
// While this example runs in a single process, that is just to make
// it easier to start and stop the example. The client task signals to
// main when it's ready.
#include "czmq.h"
#include <stdlib.h>
void dbg_write_in_file(char * txt, int nb_request) {
FILE * pFile;
pFile = fopen ("myfile.txt","a");
if (pFile!=NULL)
{
fputs (txt, pFile);
char str_nb_request[12];
sprintf(str_nb_request, "%d", nb_request);
fputs (str_nb_request, pFile);
fputs ("\n", pFile);
fclose (pFile);
}
}
static void
client_task (zsock_t *pipe, void *args)
{
zsock_t *client = zsock_new (ZMQ_DEALER);
zsock_connect (client, "tcp://localhost:5555");
printf ("Setting up test...\n");
zclock_sleep (100);
printf("child 1: parent: %i\n\n", getppid());
printf("child 1: my pid: %i\n\n", getpid());
int requests;
int64_t start;
printf ("Synchronous round-trip test...\n");
start = zclock_time ();
for (requests = 0; requests < 10000; requests++) {
zstr_send (client, "hello");
// stuck here /!\
char *reply = zstr_recv (client);
zstr_free (&reply);
// check if it does something
dbg_write_in_file("sync round-trip requests : ", requests);
// end check
}
printf (" %d calls/second\n",
(1000 * 10000) / (int) (zclock_time () - start));
printf ("Asynchronous round-trip test...\n");
start = zclock_time ();
for (requests = 0; requests < 100000; requests++) {
zstr_send (client, "hello");
// check if it does something
dbg_write_in_file("async round-trip send requests : ", requests);
// end check
}
for (requests = 0; requests < 100000; requests++) {
char *reply = zstr_recv (client);
zstr_free (&reply);
// check if it does something
dbg_write_in_file("async round-trip rec requests : ", requests);
// end check
}
printf (" %d calls/second\n",
(1000 * 100000) / (int) (zclock_time () - start));
zstr_send (pipe, "done");
}
// Here is the worker task. All it does is receive a message, and
// bounce it back the way it came:
static void
worker_task (zsock_t *pipe, void *args)
{
printf("child 2: parent: %i\n\n", getppid());
printf("child 2: my pid: %i\n\n", getpid());
zsock_t *worker = zsock_new (ZMQ_DEALER);
zsock_connect (worker, "tcp://localhost:5556");
while (true) {
zmsg_t *msg = zmsg_recv (worker);
zmsg_send (&msg, worker);
}
zsock_destroy (&worker);
}
// Here is the broker task. It uses the zmq_proxy function to switch
// messages between frontend and backend:
static void
broker_task (zsock_t *pipe, void *args)
{
printf("child 3: parent: %i\n\n", getppid());
printf("child 3: my pid: %i\n\n", getpid());
// Prepare our sockets
zsock_t *frontend = zsock_new (ZMQ_DEALER);
zsock_bind (frontend, "tcp://localhost:5555");
zsock_t *backend = zsock_new (ZMQ_DEALER);
zsock_bind (backend, "tcp://localhost:5556");
zmq_proxy (frontend, backend, NULL);
zsock_destroy (&frontend);
zsock_destroy (&backend);
}
// Finally, here's the main task, which starts the client, worker, and
// broker, and then runs until the client signals it to stop:
int main (void)
{
// Create threads
zactor_t *client = zactor_new (client_task, NULL);
assert (client);
zactor_t *worker = zactor_new (worker_task, NULL);
assert (worker);
zactor_t *broker = zactor_new (broker_task, NULL);
assert (broker);
// Wait for signal on client pipe
char *signal = zstr_recv (client);
zstr_free (&signal);
zactor_destroy (&client);
zactor_destroy (&worker);
zactor_destroy (&broker);
return 0;
}
When I run it, it looks like the program is stuck at the comment
// stuck here /!\
Then when I kill it as it does not finish, or print anything at all, I need to press five time Ctrl+C ( ^C ). Only then, it looks more verbose on the console, like it was indeed running. => Note that I delete all my printf() steps' outputs, as it was really messy to read.
When it runs, it does not write anything to the file, called by the dbg_write_in_file() function, only after sending five Ctrl+C ( ^C ).
Both client worker and broker task return the same getppid number ( my terminal ) and getpid as the program itself.
I use gcc trippingv4.c -o trippingv4 -L/usr/local/lib -lzmq -lczmq to compile.
When I try to kill it :
./trippingv4
Setting up test...
child 1: parent: 60967
child 1: my pid: 76853
Synchronous round-trip test...
^Cchild 2: parent: 60967
child 2: my pid: 76853
^Cchild 3: parent: 60967
child 3: my pid: 76853
^C^C^CE: 18-02-28 00:16:37 [76853]dangling 'PAIR' socket created at src/zsys.c:471
E: 18-02-28 00:16:37 [76853]dangling 'DEALER' socket created at trippingv4.c:29
E: 18-02-28 00:16:37 [76853]dangling 'PAIR' socket created at src/zsys.c:471
E: 18-02-28 00:16:37 [76853]dangling 'DEALER' socket created at trippingv4.c:89
Update
Thanks for the detailed answer #user3666197. In first part, the compiler does not compile the assert call so I just show the value instead and compare visually, they are the same.
int czmqMAJOR,
czmqMINOR,
czmqPATCH;
zsys_version ( &czmqMAJOR, &czmqMINOR, &czmqPATCH );
printf( "INF: detected CZMQ ( %d, %d, %d ) -version\n",
czmqMAJOR,
czmqMINOR,
czmqPATCH
);
printf( "INF: CZMQ_VERSION_MAJOR %d, CZMQ_VERSION_MINOR %d, CZMQ_VERSION_PATCH %d\n",
CZMQ_VERSION_MAJOR,
CZMQ_VERSION_MINOR,
CZMQ_VERSION_PATCH
);
Output :
INF: detected CZMQ ( 4, 1, 0 ) -version
INF: CZMQ_VERSION_MAJOR 4, CZMQ_VERSION_MINOR 1, CZMQ_VERSION_PATCH 0
The zsys_info call does compile but does not show anything on the terminal, even with a fflush(stdout) just in case so I just used printf :
INF: This system's Context() limit is 65535 ZeroMQ socketsINF: current state of the global Context()-instance has:
( 1 )-IO-threads ready
( 1 )-ZMQ_BLOCKY state
Then I changed the global context thread value with zsys_set_io_threads(2) and/or zmq_ctx_set (aGlobalCONTEXT, ZMQ_BLOCKY, false);, still blocked. It looks like zactor does not works with systems threads as zthread was... or does not gives a similar behavior. Given my experience in zeromq (also zero) probably I trying something that can't be achieved.
Update solved but unproper
My main error was to not have properly initiate zactor instance
An actor function MUST call zsock_signal (pipe) when initialized and MUST listen to pipe and exit on $TERM command.
And to not have blocked the zactor's proxy execution before it called zactor_destroy (&proxy);
I let the final code below but you still need to exit at the end with Ctrl+C because I did not figure it out how to manage $TERM signal properly. Also, zactor still appears to not use system theads. It's probably design like this but I don't know how it's work behind the wood.
// Round-trip demonstrator
// While this example runs in a single process, that is just to make
// it easier to start and stop the example. The client task signals to
// main when it's ready.
#include <czmq.h>
static void
client_task (zsock_t *pipe, void *args)
{
assert (streq ((char *) args, "Hello, Client"));
zsock_signal (pipe, 0);
zsock_t *client = zsock_new (ZMQ_DEALER);
zsock_connect (client, "tcp://127.0.0.1:5555");
printf ("Setting up test...\n");
zclock_sleep (100);
int requests;
int64_t start;
printf ("Synchronous round-trip test...\n");
start = zclock_time ();
for (requests = 0; requests < 10000; requests++) {
zstr_send (client, "hello");
zmsg_t *msgh = zmsg_recv (client);
zmsg_destroy (&msgh);
}
printf (" %d calls/second\n",
(1000 * 10000) / (int) (zclock_time () - start));
printf ("Asynchronous round-trip test...\n");
start = zclock_time ();
for (requests = 0; requests < 100000; requests++) {
zstr_send (client, "hello");
}
for (requests = 0; requests < 100000; requests++) {
char *reply = zstr_recv (client);
zstr_free (&reply);
}
printf (" %d calls/second\n",
(1000 * 100000) / (int) (zclock_time () - start));
zstr_send (pipe, "done");
printf("send 'done' to pipe\n");
}
// Here is the worker task. All it does is receive a message, and
// bounce it back the way it came:
static void
worker_task (zsock_t *pipe, void *args)
{
assert (streq ((char *) args, "Hello, Worker"));
zsock_signal (pipe, 0);
zsock_t *worker = zsock_new (ZMQ_DEALER);
zsock_connect (worker, "tcp://127.0.0.1:5556");
bool terminated = false;
while (!terminated) {
zmsg_t *msg = zmsg_recv (worker);
zmsg_send (&msg, worker);
// zstr_send (worker, "hello back"); // Give better perf I don't know why
}
zsock_destroy (&worker);
}
// Here is the broker task. It uses the zmq_proxy function to switch
// messages between frontend and backend:
static void
broker_task (zsock_t *pipe, void *args)
{
assert (streq ((char *) args, "Hello, Task"));
zsock_signal (pipe, 0);
// Prepare our proxy and its sockets
zactor_t *proxy = zactor_new (zproxy, NULL);
zstr_sendx (proxy, "FRONTEND", "DEALER", "tcp://127.0.0.1:5555", NULL);
zsock_wait (proxy);
zstr_sendx (proxy, "BACKEND", "DEALER", "tcp://127.0.0.1:5556", NULL);
zsock_wait (proxy);
bool terminated = false;
while (!terminated) {
zmsg_t *msg = zmsg_recv (pipe);
if (!msg)
break; // Interrupted
char *command = zmsg_popstr (msg);
if (streq (command, "$TERM")) {
terminated = true;
printf("broker received $TERM\n");
}
freen (command);
zmsg_destroy (&msg);
}
zactor_destroy (&proxy);
}
// Finally, here's the main task, which starts the client, worker, and
// broker, and then runs until the client signals it to stop:
int main (void)
{
// Create threads
zactor_t *client = zactor_new (client_task, "Hello, Client");
assert (client);
zactor_t *worker = zactor_new (worker_task, "Hello, Worker");
assert (worker);
zactor_t *broker = zactor_new (broker_task, "Hello, Task");
assert (broker);
char *signal = zstr_recv (client);
printf("signal %s\n", signal);
zstr_free (&signal);
zactor_destroy (&client);
printf("client done\n");
zactor_destroy (&worker);
printf("worker done\n");
zactor_destroy (&broker);
printf("broker done\n");
return 0;
}
Let's diagnose the as-is state, going step by step:
int czmqMAJOR,
czmqMINOR,
czmqPATCH;
zsys_version ( &czmqMAJOR, &czmqMINOR, &czmqPATCH );
printf( "INF: detected CZMQ( %d, %d, %d )-version",
czmqMAJOR,
czmqMINOR,
czmqPATCH
);
assert ( czmqMAJOR == CZMQ_VERSION_MAJOR & "Major: does not match\n" );
assert ( czmqMINOR == CZMQ_VERSION_MINOR & "Minor: does not match\n" );
assert ( czmqPATCH == CZMQ_VERSION_PATCH & "Patch: does not match\n" );
if this matches your expectations, you may hope the DLL-versions are both matching and found in proper locations.
Next:
may test the whole circus run in a non-blocking mode, to prove, there is no other blocker, but as briefly inspected, I have not found such option exposed in CZMQ-API, the native API allows one to flag a NOBLOCK option on { _send() | _recv() }-operations, which prevents them from remaining blocked ( which may be the case for DEALER socket instance in cases on _send()-s, when there are not yet any counterparty with a POSACK-ed .bind()/.connect() state ).
Here I did not find some tools to do this as fast as expected in native API. Maybe you will have more luck on going through this.
Test the presence of a global Context() instance, if it is ready:
add before a first socket instantiation, to be sure we are before any and all socket-generation and their respective _bind()/_connect() operation a following self-reporting row, using:
zsys_info ( "INF: This system's Context() limit is %zu ZeroMQ sockets",
zsys_socket_limit ()
);
One may also enforce the Context() instantiation manually:
so as to be sure the global Context() instance is up and running, before any higher abstracted instances ask if for implementing additional internalities ( sockets, counters, handlers, port-management, etc. )
// Initialize CZMQ zsys layer; this happens automatically when you create
// a socket or an actor; however this call lets you force initialization
// earlier, so e.g. logging is properly set-up before you start working.
// Not threadsafe, so call only from main thread. Safe to call multiple
// times. Returns global CZMQ context.
CZMQ_EXPORT void *
zsys_init (void);
// Optionally shut down the CZMQ zsys layer; this normally happens automatically
// when the process exits; however this call lets you force a shutdown
// earlier, avoiding any potential problems with atexit() ordering, especially
// with Windows dlls.
CZMQ_EXPORT void
zsys_shutdown (void);
and possibly better tune IO-performance, using this right at the initialisation state:
// Configure the number of I/O threads that ZeroMQ will use. A good
// rule of thumb is one thread per gigabit of traffic in or out. The
// default is 1, sufficient for most applications. If the environment
// variable ZSYS_IO_THREADS is defined, that provides the default.
// Note that this method is valid only before any socket is created.
CZMQ_EXPORT void
zsys_set_io_threads (size_t io_threads);
This manual instantiation gives one an additional benefit, from having the instance-handle void pointer, so that one can inspect it's current state and shape by zmq_ctx_get() tools:
void *aGlobalCONTEXT = zsys_init();
printf( "INF: current state of the global Context()-instance has:\n" );
printf( " ( %d )-IO-threads ready\n", zmq_ctx_get( aGlobalCONTEXT,
ZMQ_IO_THREADS
)
);
printf( " ( %d )-ZMQ_BLOCKY state\n", zmq_ctx_get( aGlobalCONTEXT,
ZMQ_BLOCKY
)
); // may generate -1 in case DLL is << 4.2+
...
If unhappy with signal-handling, one may design and use another one:
// Set interrupt handler; this saves the default handlers so that a
// zsys_handler_reset () can restore them. If you call this multiple times
// then the last handler will take affect. If handler_fn is NULL, disables
// default SIGINT/SIGTERM handling in CZMQ.
CZMQ_EXPORT void
zsys_handler_set (zsys_handler_fn *handler_fn);
where
// Callback for interrupt signal handler
typedef void (zsys_handler_fn) (int signal_value);

Issues with socket and server in C (Name or service not known error)

I am working on a client/server program that is supposed to take user input (two integers) and allow the user to calculate those to receive an answer.
When I run my program there seems to be an issue with either connecting to the client or opening the directory and I'm not sure what it could be. I'm entirely new to setting up servers and utilizing directories to read and write .txt files to.
Here are the parts of code that I think might be wrong and causing the issues I am facing, which is the program asks for a port number to connect to (2000 is what is recommended to use) so I enter that and then nothing happens.
// PURPOSE: To run the server by 'accept()'-ing client requests from
// 'listenFd' and doing them.
void doServer (int listenFd)
{
/* Application validity check: */
/* Server clients: */
pthread_t threadId;
pthread_attr_t threadAttr;
int threadCount = 0;
int *iPtr;
/* YOUR CODE HERE: */
while(1)
{
/* Accept connection to client: */
int connfd = accept(listenFd, NULL, NULL); //if I change this to getServerFileDescriptor (another function within the code, it will continuously loop through threadNumbers and do nothing as well).
/* Malloc memory for two integers: */
iPtr = (int *)calloc(2, sizeof(int));
/*Put file descriptor in the first space: */
iPtr[0] = listenFd; // or just listenFd not sure
/* put threadCount into the second space and increment: */
iPtr[1] = threadCount++;
/* Creates detached thread for handleClient and passes the address of iPtr */
pthread_attr_init(&threadAttr);
pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
pthread_create(&threadId, &threadAttr, handleClient, (void*)iPtr);
pthread_join(threadId, NULL);
pthread_attr_destroy(&threadAttr);
}
}
void* handleClient(void* vPtr)
{
/* Read command: */
char buffer[BUFFER_LEN];
char command;
int fileNum;
char text[BUFFER_LEN];
int shouldContinue = 1;
int threadNum;
int fd;
/* Cast void* vPtr back to an int */
int *iPtr = (int *)vPtr;
/* Assign file descriptor to a local value named 'fd'*/
fd = iPtr[0];
/* Assign thread number to local value named 'threadNum'*/
threadNum = iPtr[1];
free(iPtr);
while (shouldContinue)
{
memset(buffer,'\0',BUFFER_LEN);
memset(text ,'\0',BUFFER_LEN);
read(fd,buffer,BUFFER_LEN);
printf("Thread %d received: %s\n",threadNum,buffer);
sscanf(buffer,"%c %d \"%[^\"]\"",&command,&fileNum,text);
/* YOUR CODE HERE: */
if(command == DIR_CMD_CHAR)
{
/* 1. Open the current directory (named "."). If an error occurs then just send STD_ERROR_MSG back to the client: */
DIR* dirPtr = opendir(".");
struct dirent* entryPtr;
/* If error occurs send STD_ERROR_MSG to client: */
if ((dirPtr = opendir (".")) == NULL) {
{
write(fd, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
//return(EXIT_FAILURE);
}
/* Read as many entries that will fit into BUFFER_LEN
put as many entries into the buffer and send the buffer to client
d_name=entryPtr into the bufffer using strcat_s,
make sure buffer starts empty
buffer[0]='\n';
add new line char using stringcat "\n"
make sure do not go over buffer lengh */
if (dirPtr)
{
while ((entryPtr = readdir(dirPtr)) != NULL)
{
buffer[0]='\0';
int i;
int sizebuf = sizeof(buffer);
for (i = 0; i < sizebuf; i++)
{
strcat(buffer,entryPtr->d_name);
strcat(buffer,"\n");
}
}
}
/* 3. Close directory */
closedir(dirPtr);
}
Here's how the correct output should look.
$ ./mathClient Machine name [localhost.localdomain]? (I just pressed enter)
Port number? 2000
What would you like to do:
(1) List files
(2) Read a math file
(3) Write a math file
(4) Calculate a math file
(5) Delete a math file
(0) Quit
Your choice? 1
Sending "l"
0.bc
Here are the instructions for the code that I am having trouble with.
Implementing doServer(int listenFd) (10 Points):
doServer() should have a loop in which it waits for a client to connect to listenFd. When a client does, it should:
malloc() enough memory for 2 integers
put the file descriptor from accept() in one of those spaces
put the value of threadCount in the other space, and increment threadCount
Make a detached thread to handle this new client. I called my function handleClient(), but you may call yours whatever. Pass the address of your malloc()-ed array.
The loop should then go back for another accept().
void* handleClient(void* vPtr) (10 Points):
(Or whatever you call your function that runs a thread for the client.)
The thread id and the file descriptor are passed, but they come in as a void* pointer.
Use another pointer to cast back to int*
Save the file descriptor and thread number in local vars
free() the memory
Print the thread number and do a loop like this:
// II.B. Read command:
char buffer[BUFFER_LEN];
char command;
int fileNum;
char text[BUFFER_LEN];
int shouldContinue = 1;
while (shouldContinue)
{
text[0] = '\0';
read(fd,buffer,BUFFER_LEN);
printf("Thread %d received: %s\n",threadNum,buffer);
sscanf(buffer,"%c %d \"%[^\"]\"",&command,&fileNum,text);
// YOUR CODE HERE
}
It read()s a line of text from the client into buffer[], and parses the line into a command character, fileNum integer, and quote-delineated text[] string. (The fileNum and text[] may or may not be given, depending upon the value of command.)
Then do the following operations based upon the value of command. Except for QUIT_CMD_CHAR I strongly recommend using a different function for each!
When the function ends just have it do:
printf("Thread %d quitting.\n",threadNum);
return(NULL);
command == DIR_CMD_CHAR (15 Points):
Open the current directory (named "."). If an error occurs then just send STD_ERROR_MSG back to the client.
Copy as many entries that will fit into a buffer of length BUFFER_LEN. Be sure to put a separating '\n' after each entry.
Close the directory.
Any help would be appreciated, if you need the full code I could send that to you if that would help.
EDIT: Here are two additional functions, one called getPortNum() and another called getServerFileDescriptor() which address receiving a port number and setting up sockets for the connection. Additionally I included the main() which utilizes these.
// PURPOSE: To decide a port number, either from the command line arguments
// 'argc' and 'argv[]', or by asking the user. Returns port number.
int getPortNum (int argc,
char* argv[]
)
{
// I. Application validity check:
// II. Get listening socket:
int portNum;
if (argc >= 2)
portNum = strtol(argv[1],NULL,0);
else
{
char buffer[BUFFER_LEN];
printf("Port number to monopolize? ");
fgets(buffer,BUFFER_LEN,stdin);
portNum = strtol(buffer,NULL,0);
}
// III. Finished:
return(portNum);
}
// PURPOSE: To attempt to create and return a file-descriptor for listening
// to the OS telling this server when a client process has connect()-ed
// to 'port'. Returns that file-descriptor, or 'ERROR_FD' on failure.
int getServerFileDescriptor
(int port
)
{
// I. Application validity check:
// II. Attempt to get socket file descriptor and bind it to 'port':
// II.A. Create a socket
int socketDescriptor = socket(AF_INET, // AF_INET domain
SOCK_STREAM, // Reliable TCP
0);
if (socketDescriptor < 0)
{
perror(THIS_PROGRAM_NAME);
return(ERROR_FD);
}
// II.B. Attempt to bind 'socketDescriptor' to 'port':
// II.B.1. We'll fill in this datastruct
struct sockaddr_in socketInfo;
// II.B.2. Fill socketInfo with 0's
memset(&socketInfo,'\0',sizeof(socketInfo));
// II.B.3. Use TCP/IP:
socketInfo.sin_family = AF_INET;
// II.B.4. Tell port in network endian with htons()
socketInfo.sin_port = htons(port);
// II.B.5. Allow machine to connect to this service
socketInfo.sin_addr.s_addr = INADDR_ANY;
// II.B.6. Try to bind socket with port and other specifications
int status = bind(socketDescriptor, // from socket()
(struct sockaddr*)&socketInfo,
sizeof(socketInfo)
);
if (status < 0)
{
perror(THIS_PROGRAM_NAME);
return(ERROR_FD);
}
// II.B.6. Set OS queue length:
listen(socketDescriptor,5);
// III. Finished:
return(socketDescriptor);
}
int main (int argc,
char* argv[]
)
{
// I. Application validity check:
// II. Do server:
int port = getPortNum(argc,argv);
int listenFd = getServerFileDescriptor(port);
int status = EXIT_FAILURE;
if (listenFd >= 0)
{
doServer(listenFd);
close(listenFd);
status = EXIT_SUCCESS;
}
// III. Finished:
return(status);

When creating threads, some are getting a thread ID 0

I have a server application that creates new thread for every incoming request.
However, every once in a while, it will create a thread with thread ID = 0 (used pthread_equal to check this). I have a structure that contains the thread ID that I pass to the function specified in pthread_create, and am checking this there.
Why would a thread get created with ID = 0?
Is there anything I can do if this happens? I cannot use this thread and want to exit it immediately.
=====================================================================
typedef struct
{
pthread_t tid;
other_struct_t Other;
} data_ptr_t;
void * worker(void * arg)
{
data_ptr_t local_data;
data_ptr_t * incoming_data = (data_ptr_t *) arg;
if (NULL == incoming_data || NULL == incoming_data->Other)
{
printf("invalid input\n");
}
else if (pthread_equal(incoming_data->tid, 0))
{
printf("invalid thread id\n");
}
else
{
// add to global thread pool
// do other stuff here
// remove from global thread pool
}
}
int main()
{
// server socket stuff
while (1)
{
// if incoming connection is valid
data_ptr_t data;
int error = pthread_create(&(data.tid), NULL, (void * (*) (void *)) worker, (void *) &data);
if (0 != errror)
{
printf("could not create thread (%d)\n", error);
}
else
{
pthread_detach(data.tid);
printf("thread dispatched\n");
}
}
}
Note: If the number of threads I'm creating is under 50 or so, it works fine. Upwards of 70, most threads go through just fine, the rest end up printing the "invalid thread id".
Note: This is on Linux.
You can't do this:
while (1)
{
// if incoming connection is valid
data_ptr_t data;
int error = pthread_create(&(data.tid),
NULL, (void * (*) (void *)) worker, (void *) &data);
your data_ptr_t is a local variable on the stack. On the next iteration of the while loop, that variable is destroyed/gone/not-valid.
The while loop might start another iteration long before the new worker thread starts running and makes use of the data you pass to it. Instead, dynamically allocate the data you pass to the worker thread so you can be sure it's still valid.

Resources