I'm trying to make a little chat program after reading Beej's guide to programming.
And then I was thinking about the basics of the program itself, and I don't know how to print output of recv() and get input for send() at the same time, because the client can always write something and send, but how is it possible to also print something while he's trying to input ?
I thought about threads, and I learned a little bit about them, and I created 2 simple threads: The first one, prints a sentence every 3 seconds, and the second one get input, this little program of-course had a lot of issues, for ex. if you started typing, and the other thread needs to print something, it will simply take what you wrote, and print it with itself output.
Here is the code, I tried to recreate it, I hope you guys can help me ..
pthread_t tid[2];
void* printse();
void* getinput();
int main(int argc, char *argv[])
{
int error;
error = pthread_create(&(tid[1]), NULL, &getinput, NULL);
if(error != 0)
{
printf("ERROR\n");
} else {
printf("NOERROR\n");
}
error = pthread_create(&(tid[2]), NULL, &printse, NULL);
if(error != 0)
{
printf("ERROR\n");
} else {
printf("NOERROR\n");
}
sleep(5000);
return 0;
}
void* printse()
{
while(1)
{
printf("POTATO\n");
sleep(3);
}
return NULL;
}
void* getinput()
{
char *input;
while(scanf("%s", input) != EOF)
{
printf("-%s\n", input);
}
return NULL;
}
You have undefined behavior in your code: You haven an uninitialized pointer input in getinput.
Uninitialized (non-static) local variables have an indeterminate value, and it will seem to be random. As the value is indeterminate (and seemingly random) the scanf call will write to some unknown place in memory, overwriting whatever was there.
You could easily solve this by making input an array.
Related
My program it's pretty big, so I'll highlight the main problem and add some details about it.
First part of my code:
int myPipe[2]; //A global variable, so I don't have to pass it to future functions
int main(int argc, char *args[])
{
mode_t pUmask = umask(0000); //Obsolete variable to my problem
errno = 0; //Obsolete variable to my problem
char pattern[2500] = "Test1"; //Obsolete variable to my problem
int p = 0; //DEFAULT NUMBER OF PROCESSES
int deep = 0; //Obsolete variable to my problem
int n = 1; //Obsolete variable to my problem
if(pipe(myPipe))
{
perror("Pipe Error: ");
exit(-1);
}
if( (write(myPipe[1], &p, (sizeof(int)*3))) == -1) //First write works
{
perror("write: ");
exit(-1);
}
//Then a bunch of code releated to file reading
}
Second part:
{
//in another function
//The part where I create fileName
char* fileName = calloc(strlen(fileData->d_name)+4, sizeof(char));
strcpy(fileName, fileData->d_name);
}
Third part:
//in another another function
if(S_ISREG(data.st_mode))
{
printf("\tfileName: %s\n", fileName); //Regular print of the right fileName
printf("\t\tOh boy! It's a regular.\n");
printf("\tfileName: %s\n", fileName); //Regular print of the right fileName
if((read(myPipe[0], &p, (sizeof(int)*3))) == -1) //First time I read
{
perror("\t\t read: ");
exit(-1);
}
printf("fileName: %s", fileName); //SEGMENTATION FAULT
There is a bunch of code in between, but it doesn't affect the fileName at all (in fact, up until the "read", fileName was printed flawlessly), and after it a SEGMENTATION FAULT happens.
At one point by changing the printfs locations I was able to get the fileName AFTER the read, which was basically the fileName value("File1") followed by the p integer value(0), which created the new corrupted fileName("File10").
So what's happening? I reserved the space for fileName, I passed the fileName pointer to the following functions up to that read, and supposedly the fd should have it's own adress space as well. HELP.
P.s. if you need more info, I'm willing to give it to you, even the full code, but it's REALLY complicated, and I think I gave you enough proof that fileName doesn't get corrupted at all until the read part, THANK YOU.
P.p.s.
I never close either of the "MyPipe" extremes, since I have to use them multiple times, I wanted to close them at the end of the program.
The statements that write and read the pipe are causing undefined behavior. p is declared:
int p;
But when you write and read it through the pipe, you use sizeof(int)*3, so you're accessing outside the object.
Change those statements to use just sizeof p.
For a class assignment I am required to develop a single program, that -when opened in two separate windows - allows the user to type on one window and have the entered text appear on the other, while the other window can also type and have their text appear on the first window.
This was first implemented using two separate programs, one which read the input from stdin, wrote it to a pipe, called fflush on the pipe, then got data from the pipe and put it into stdout before calling fflush on stdout, and the other which did basically the exact opposite.
I'm here because I'm struggling to make the single program version work and I'm not sure if I understand threading correctly.
Here's my main function:
int main()
{
pthread_t threadID[2];
pthread_mutex_init(&globalLock, NULL);
pthread_create(&threadID[0], NULL, InputToPipe, NULL);
pthread_create(&threadID[1], NULL, PipeToOutput, NULL);
pthread_join(threadID[0], NULL);
pthread_join(threadID[1], NULL);
pthread_mutex_destroy(&globalLock);
return 0;
}
As I understand it, this will initialize a global lock (which I'm not sure if I need or not) and then create two threads. The first thread will call InputToPipe and the second will call PipeToOutput. Both should enter their respective functions nearly simultaneously. Once in InputToPipe (which looks like this)
void *InputToPipe()
{
pthread_mutex_lock(&globalLock);
char buffer[100];
FILE *output = fopen("my.pipe2", "w");
if (output == NULL)
{
printf("Error opening pipe\n");
return NULL;
}
while (fgets(buffer, sizeof(buffer), stdin))
{
fputs(buffer, output);
fflush(output);
}
pthread_mutex_unlock(&globalLock);
return NULL;
}
A lock is set, which was intended to keep the second instance of the program from accessing the first function. I thought that this would cause the second instance of the program to only run the PipeToOutput function (shown below),
void *PipeToOutput()
{
char buffer[100];
FILE *input = fopen("my.pipe", "r");
if (input == NULL)
{
printf("Error opening pipe\n");
return NULL;
}
while (fgets(buffer, sizeof(buffer), input))
{
fputs(buffer, stdout);
fflush(stdout);
}
return NULL;
}
but instead I think it would block the second program from doing anything as the first pipe is joined first, and that cannot be done until it is unlocked by the first program, which will not happen before the program is terminated. Needless to say, I am confused and pretty sure that most of my logic is off, but I was unable to find examples or explanations about using two threads to run two different functions in two different console windows (unless I completely misunderstood the assignment somehow and it's just one function running twice, but I don't think that's the case). I would appreciate either some help fixing this program so I can use it as an example to understand what the threads are doing, or just an explanation on how I would implement the threads and why. I know it's probably stupidly simple but I am having trouble with the concept. Thanks in advance.
If the idea is that my.pipe is used to transfer messages from the first program to the second, and my.pipe2 is used to transfer messages in the opposite direction, then it appears that both programs should be identical except swapping my.pipe and my.pipe2.
It sounds like they want each program to have two threads, one of which is responsible for reading from the first pipe and writing to stdout, and the other responsible for reading from stdin and writing to the second pipe.
That being the case, your existing functions look correct with the exception that you don't need the lock at all - all it's doing is stopping both threads from running at once, and your threads aren't sharing any state at all. Your second copy of the program would be the same except swapping my.pipe and my.pipe2 around.
Note that your InputToPipe and PipeToOutput functions contain an identical loop that differs only in the FILE * variables used, so you could separate that out into its own function:
void FileToFile(FILE *output, FILE *input)
{
char buffer[100];
while (fgets(buffer, sizeof(buffer), input))
{
fputs(buffer, output);
fflush(output);
}
}
void *InputToPipe()
{
FILE *output = fopen("my.pipe2", "w");
if (output == NULL)
{
printf("Error opening pipe\n");
return NULL;
}
FileToFile(output, stdin);
fclose(output);
return NULL;
}
void *PipeToOutput()
{
FILE *input = fopen("my.pipe", "r");
if (input == NULL)
{
printf("Error opening pipe\n");
return NULL;
}
FileToFile(stdout, input);
fclose(input);
return NULL;
}
In fact you could go further than this: if you opened the pipes in the main() process before starting the threads, you could just pass the pair of FILE *input and FILE *output variables to the thread functions, which would let you use the same thread function (with different parameters) for each thread.
I am trying to get name of the input, output, and data files from the array for further processing. However, I am getting a weird error or problem. So, my program is not reaching the for loop. It does not even print the statement before the for loop. However, I tried using the debugger and the program is correctly printing step by step. So, when I run it does not print and when I debug step by step it prints. That is Weird!
char *method;
method=malloc(25);
method=NULL;
char *dataFileName;
char *inputMethod;
inputMethod=malloc(25);
inputMethod=NULL;
char *inputFileName;
char *outputMethod;
outputMethod=malloc(25);
outputMethod=NULL;
char *outputFileName;
char *commandArray[]={"if=q.txt","of=output.txt"};
char**args=(char**) malloc(sizeof(char*)*256);
args=commandArray;
int i;
printf("Before second for");
for(i=0;i<2;i++)
{
printf("I am here");
if(*args[i]=='d')
{
method=strtok_r(args[i],"=",&dataFileName);
printf("The method given is %s",method);
printf("Data File Name is %s",dataFileName);
}
else if(*args[i]=='o')
{
outputMethod=strtok_r(args[i],"=",&outputFileName);
printf("The output method given is %s",outputMethod);
printf("output File Name is %s",outputFileName);
}
else
{
inputMethod=strtok_r(args[i],"=",&inputFileName);
printf("The input method given is %s",inputMethod);
printf("Input File Name is %s",inputFileName);
}
}
if(method==NULL)
{
dataFileName=malloc(256);
printf("Please Enter A File Name");
scanf("%255s",dataFileName);
printf("%s",dataFileName);
}
if((inputMethod==NULL)||(outputMethod==NULL) )
{
char* array[]={"stdin","stdout"};
if(inputMethod==NULL)
inputMethod=array[0];
if(outputMethod==NULL)
outputMethod=array[1];
}
I am developing using Netbeans in C. The above code is written inside main. Thanks!
i intentionally left the previous answer because understanding memory allocation is trivial in programming in c specially. and as i see you have a big issue with that.
but still you have issue in nearly every thing. in my actual answer, i will try to simplify you how to use strtok, to split string and parse it. i guess this is the second main problem with your code.
the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char commandArray[][256]={
"if=q.txt",
"of=output.txt"
};
char infile[256], outfile[256];
for(int i=0; i<2;i++){
char *ptr,*cmd;
cmd=commandArray[i];
ptr=NULL;
printf("parsing command '%s'\n",cmd);
cmd=strtok(cmd,"=");
ptr=strtok(NULL,"=");
if(!cmd){
printf("Error parsing the string '%s'\n",commandArray[i]);
exit(1);
}
if (strcmp(cmd,"if")==0){
strcpy(infile,ptr);
}
else if (strcmp(cmd,"of")==0){
strcpy(outfile,ptr);
}
else{
printf("unknow token '%s'\n",cmd);
exit(1);
}
}
printf(
"\n\n"
"input file: '%s'\n"
"output file: '%s'\n"
"\n\n",
infile,outfile);
return 0;
}
the main problem is this:
char *method;
method=malloc(25);//allocating space for 25 char
method=NULL; // throwing up the allocation without freeing it;
// now the allocation is lost
// now method is useless (it is null)
Ok, here is the deal...i remember creating a program past week that required me to open a file in binary mode and write data to it. At first, i tried using the fopen function, checking if the result is ok, then try to write data. I remember that at first try, the fwrite operation wasn't working. Then, after moving declaration of variables from a place to another, i was finally able to make the fwrite to insert data to the file.
Now, i need to create another similar program to do some other stuff, so i wanted to use the same allocation code (actually, i wanted to create a specific function to do the same), and here is what i was able to come up with:
#include <stdio.h>
int openfile(FILE *main, char *name, int option);
int main(void)
{
FILE *main;
int header_init;
int result;
switch (openfile(main,"main_file.bin",1)) {
case 1:
header_init = -1;
//fseek(main,0,SEEK_SET); --> useless
fwrite(&header_init,sizeof(int),1,main);
printf("ftell = %d\n",ftell(main)); break;
case 2:
fread(&header_init,sizeof(int),1,main);
printf("%d\n",header_init); break;
default:
printf("Error trying to open file\n");
}
printf("header_init is %d\n",header_init);
fclose(main); exit(0);
}
int openfile(FILE *main, char *name, int option)
{
int result_alloc;
int F_OK;
if (result_alloc = access (name, F_OK) != 0) {
printf("File not found, allocating a new one\n");
if ((main= fopen(name,"w+b")) != NULL) return 1;
}
else {
printf("File exist, allocating as r+b\n");
if ((main= fopen(name,"r+b")) != NULL) return 2;
}
printf("Failure trying to open");
return 0;
}
For some unfortunate reason, the fwrite operation is not writing -1 to the allocated file. My intention with this program is so that it will always check for existence of that specific file: if there is one in place, simply open it with r+b to allow update functions without overwriting the actual file contents. Otherwise, allocate a new one with a header value of -1 (i will use this file as a record file with chained list structure).
Seriously, i cannot understand why this is not working. The idea is the same of my previous program. The only thing that changed is that i created a function, because this is going to happen me later (because of the 3rd parameter that will allow me to reduce my code and make it more "readable" - at least this is the intention!). I HAVE to admit that i have some attention to details problem, but i am working hard to get better at it, i am probably missing something stupid in this code, but after hours looking at it i really wanted to ask here for some help. Thanks
Edit: I am running it under z/Linux. What i am trying to understand is, why the code above doesn't write -1 to the file, but the one below writes ok?
#include <stdio.h>
int main(void)
{
FILE *main;
int result_alloc;
int header_init;
int F_OK;
if (result_alloc = access ("test.bin", F_OK) != 0) {
printf("File not found, allocating a new one\n");
if ((main = fopen("test.bin","w+b")) == NULL) {
printf("Failure trying to open file");
return 1;
}
else {
header_init = -1;
printf("current pos is: w+b %d\n",ftell(main));
fwrite(&header_init,sizeof(int),1,main);
printf("current pos is: write header_init %d\n",ftell(main));
}
}
else {
if ((main = fopen("test.bin","r+b")) == NULL) {
printf("Failure trying to open file");
return 2;
}
else {
printf("current pos is: r+b %d\n",ftell(main));
fread(&header_init,sizeof(int),1,main);
printf("current pos is: read header_init %d\n",ftell(main));
}
}
}
The main issue that the assignment to the main variable inside of the openfile function is not seen by the calling function. Because C is pass by value, you're only changing the value of the function parameter, not the value of the variable that was passed in. So when openfile returns, the main variable inside of the main function is unchanged.
What you need to do is pass the address of that variable to the function, then within the function you dereference the local variable (which is a pointer) and assign a value to the dereferenced variable.
Also, it's not a good idea to have a variable with the same name as a function as it hides the function in that scope and can cause confusion.
So you would define your function as follows:
int openfile(FILE **fp, char *name, int option);
You would then call it like this (changing the name of the main variable to fp):
FILE *fp;
...
openfile(&fp,"main_file.bin",1)
Then inside of openfile, you dereference fp to change the value in the calling function:
*fp = fopen(name,"w+b")
The reason why the second code sample is working is that you're assigning directly to a local variable and then using that same variable later on in the function.
Also, you're "lucky" that the second piece of code is working because you did this:
int F_OK;
F_OK is already defined in unistd.h, where access() is defined. So by doing this you're redeclaring it and not giving it a value, causing undefined behavior. Get rid of this definition, and #include <unistd.h>, and the call to access() is guaranteed to work as expected.
The following is a code snippet from my read from pipe function. This executes properly and verified that the data is got into buffer .
int readFrom(char *buffer)
{
int nread;
if((nread = read(readfd,buffer,100)) < 0)
{
printf("\nerror in reading data from FIFO\n");
return(-1);
}
buffer[nread]='\0';
return(0);
}
In the above example nread is less than 100 . I am using GCC-4.7.0.
We had an abstraction layer for the above function like below :
int pipe_input(char *parmPtr, int size)
{
char readMsg[100];
if( readFrom((char *)&readMsg) == -1)
return ERROR;
if (strlen(readMsg) < 1)
{
printf("Incorrect Input\n");
return ERROR;
}
strncpy(parmPtr, readMsg, ((size < 100)?size:100));
return 0;
}
In the above function as well it was verified that read message is proper and parmptr is properly loaded with the value. But in the function Where i am trying to call pipe_input I am getting a sigsegv. This happens with GCC-4.7.0 but the same code compiled with GCC-4.2.4 executes fine. I verified the warnings, but there are no warning for the above. Any pointers would be highly helpful.
Below code snippet for calling pipe_input :
int Calling_func(void)
{
char alpha[100] ;
pipe_input(alpha,100);
printf("alpha value is %s \r\n",alpha);
}
getting sigsegv at the print statement.
You have off-by-one errors in your code. Your array has 100 elements, but you're not taking NULL-termination into account:
strncpy(parmPtr, readMsg, ((size < 100)?size:100));
and:
buffer[nread]='\0';
The last element is buffer[99] (since array indices start from 0, not 1,) but you can write to buffer[100]. This can result in a segfault.
You should probably declare all arrays with a size of 101 instead and see if it helps. If you're on Linux, you should also run your program in Valgrind; it can tell you exactly how the segfault occurred.