linux kernel + conditional statements - c

I basically am running into a very odd situation in a system call that I am writing. I want to check some values if they are the same return -2 which indicates a certain type of error has occurred. I am using printk() to print the values of the variables right before my "else if" and it says that they are equal to one another but yet the conditional is not being executed (i.e. we don't enter the else if) I am fairly new to working in the kernel but this seems very off to me and am wondering if there is some nuance of working in the kernel I am not aware of so if anyone could venture a guess as to why if I know the values of my variables the conditional would not execute I would really appreciate your help
//---------------------------------------//
/* sys_receiveMsg421()
Description:
- Copies the first message in the mailbox into <msg>
*/
asmlinkage long sys_receiveMsg421(unsigned long mbxID, char *msg, unsigned long N)
{
int result = 0;
int mboxIndex = checkBoxId(mbxID);
int msgIndex = 0;
//acquire the lock
down_interruptible(&sem);
//check to make sure the mailbox with <mbxID> exists
if(!mboxIndex)
{
//free our lock
up(&sem);
return -1;
}
else
mboxIndex--;
printk("<1>mboxIndex = %d\nNumber of messages = %dCurrent Msg = %d\n",mboxIndex, groupBox.boxes[mboxIndex].numMessages, groupBox.boxes[mboxIndex].currentMsg );
//check to make sure we have a message to recieve
-----------CODE NOT EXECUTING HERE------------------------------------------------
if(groupBox.boxes[mboxIndex].numMessages == groupBox.boxes[mboxIndex].currentMsg)
{
//free our lock
up(&sem);
return -2;
}
//retrieve the message
else
{
//check to make sure the msg is a valid pointer before continuing
if(!access_ok(VERIFY_READ, msg, N * sizeof(char)))
{
printk("<1>Access has been denied for %lu\n", mbxID);
//free our lock
up(&sem);
return -1;
}
else
{
//calculate the index of the message to be retrieved
msgIndex = groupBox.boxes[mboxIndex].currentMsg;
//copy from kernel to user variable
result = copy_to_user(msg, groupBox.boxes[mboxIndex].messages[msgIndex], N);
//increment message position
groupBox.boxes[mboxIndex].currentMsg++;
//free our lock
up(&sem);
//return number of bytes copied
return (N - result);
}
}
}
UPDATE: Solved my problem by just changing the return value to something else and it works fine very weird though

Please remember to use punctuation; I don't like running out of breath while reading questions.
Are you sure the if block isn't being entered? A printk there (and another in the corresponding else block) would take you one step further, no?
As for the question: No, there isn't anything specific to kernel code that would make this not work.
And you seem to have synchronization covered, too. Though: I see that you're acquiring mboxIndex outside the critical section. Could that cause a problem? It's hard to tell from this snippet, which doesn't even have groupBox declared.

Perhaps numMessages and/or currentMsg are defined as long?
If so, your printk, which uses %d, would print just some of the bits, so you may think they're equal while they are not.

Related

Variable loses its value C

I'm working on this project where a user has to guess a word (wordToGuess) and he has a number of attempts.
The problem is that the variable "wordToGuess" loses its value when the code arrives in the point marked ("HERE LOSES ITS VALUE). I don't know how to solve this problem, I've tried in many ways. Thank u for your help!
(checkExistence is a function that checks if the word is present in the dictionary)
void newGame(node* head){
char wordToGuess[10];
char attempt[10];
int numberOfAttempts = 0;
if (scanf("%s" , wordToGuess) != 1){
printf("error1");
}
getchar();
if (scanf("%d", &numberOfAttempts) != 1){
printf("error2");
}
getchar();
while(numberOfAttempts > 0){
if (scanf("%s", attempt) != EOF){
if (attempt[0] != '+'){
if (checkExistence(head, attempt) == false){
printf("not_exists\n");
}else{
if (strcmp(wordToGuess, attempt) == 0){
printf("ok\n");
return;
}else{
//code
numberOfAttempts--;
}
}
}else{
if (attempt[0] == '+' && attempt[1] == 's'){
//HERE LOSES ITS VALUE
}else if (attempt[0] == '+' && attempt[1] == 'i'){
//other code
}
}
}else{
printf("ko");
return;
}
}
return;
}
Here a test case:
2rj9R (wordToGuess)
18 (numerAttemps)
DP3wc (attempt)
7PGPU (attempt)
2rz9R (attempt)
+print_list (from this point I lose the value of wordToGuess)
2rj9R (attempt)
As the others have point, you're probably causing a buffer overflow in your attempt buffer which overwrites your wordToGuess buffer since your attempt and wordToGuess buffer is stored like this in your memory:
<attempt buffer> | <word To Guess>
You have two possible fixes for this (as the comments have said...):
A little fix would be to set a limit of how many characters should be read from stdin to scanf like this:
scanf("%9s" , wordToGuess) // you need 9, because your buffer can store up to
// 10 bytes but don't forget that `scanf` is also
// addinng `\0` for you!
and don't forget to flush the rest of the user input if you want that the user should be only able to insert at most 9 characters!
Increase the buffer size of your attempt (and wordToGuess) buffer but also add those read-limits for scanf which is described in the first point.
At the indicated point of the code where wordToGuess appears to lose its value, it is a dead variable. If you're looking at optimized code in a debugger, you may find that the variable doesn't exist there any more.
At a given point in a program, a dead variable is one which is never used past that point. All control flows out of that point reach the termination of that code, without ever using the variable again. Simple example:
{
int x = 3;
// x is live here: there is a next reference
printf("%d\n", x);
// x is now dead: it is not referenced after the above use
printf("foo\n");
}
In the generated code, the compiler may arrange to re-use the resources tied to a dead variable as soon as it is dead: give its register and memory location to something else.
In the debugger, if we put a breakpoint on the printf("foo\n") and try to examine x, we might get a strange result.
To have the best chance of seeing the expected result (that x still exists, and is retaining its most recent value), we have to compile with optimizations disabled.

Is there a suggested way to deal with errors in C?

There are two main ways,which is better?
Deal with error right now.
int func(){
rv = process_1();
if(!rv){
// deal with error_1
return -1;
}
rv = process_2();
if(!rv){
// deal with error_1
// deal with error_2
return -1;
}
return 0;
}
Deal with errors at go-to. I found a lot of this style of code in the Linux kernel code.
int func(){
rv = process_1();
if(!rv){
goto err_1
}
rv = process_2();
if(!rv){
goto err_2;
}
return 0;
err_2:
// deal with error_2
err_1:
// deal with error_1
return -1;
}
This is really prone to become a flame war, but here my opinion :
A lot of people will say that goto is inherently evil, that you should never use it.
While I can agree to a certain degree, I also can say that when it come to clean multiple variable (like by using fclose / free / etc etc), I find goto to be the cleanest (or more readable, at least) way of doing it.
To be clear, I advise to always use the simplest way for error handling, not using always goto.
For exemple,
bool MyFunction(void)
{
char *logPathfile = NULL;
FILE *logFile = NULL;
char *msg = NULL;
bool returnValue = false;
logPathfile = malloc(...);
if (!logPathfile) {
// Error message (use possibly perror (3) / strerror (3))
goto END_FUNCTION;
}
sprintf(logPathfile, "%s", "/home/user/exemple.txt");
logFile = fopen(logPathfile, "w");
if (!logFile) {
// Error message (use possibly perror (3) / strerror (3))
goto END_FUNCTION;
}
msg = malloc(...);
if (!msg) {
// Error message (use possibly perror (3) / strerror (3))
goto END_FUNCTION;
}
/* ... other code, with possibly other failure test that end with goto */
// Function's end
returnValue = true;
/* GOTO */END_FUNCTION:
free(logPathfile);
if (logFile) {
fclose(logFile);
}
free(msg);
return returnValue;
}
By using goto to handle the error, you now really reduce the risk to do memory leak.
And if in the futur you have to add another variable that need cleaning, you can add the memory management really simply.
Or if you have to add another test (let's say for example that the filename should not begin by "/root/"), then you reduce the risk to forgetting to free the memory because the goto whill handle it.
Like you said it, you can also use this flow structure to add rollback action.
Depending the situation, you maybe don't need to have multiple goto label thougth.
Let's say that in the previous code, if there is an error, we have to delete the created file.
Simply add
/* rollback action */
if (!returnValue) {
if (logPathfile) {
remove(logPathfile);
}
}
rigth after the goto label, and you're done :)
=============
edit :
The complexity added by using goto are, as far as I know, the following :
every variable that will be cleaned or use to use clean have to be intialized.
That should not be problematic since setting pointer to a valid value (NULL or other) should always be done when declaring the variable.
for example
void MyFunction(int nbFile)
{
FILE *array = NULL;
size_t size = 0;
array = malloc(nbFile * sizeof(*array));
if (!array) {
// Error message (use possibly perror (3) / strerror (3))
goto END_FUNCTION;
}
for (int i = 0; i < nbFile; ++i) {
array[i] = fopen("/some/path", "w");
if (!array[i]) {
// Error message (use possibly perror (3) / strerror (3))
goto END_FUNCTION;
}
++size;
}
/* ... other code, with possibly other failure test that end with goto */
/* GOTO */END_FUNCTION:
/* We need size to fclose array[i], so size should be initialized */
for (int i = 0; i < size; ++i) {
flcose(array[i]);
}
free(array);
}
(yeah, I know that If I had use calloc instead of malloc, I could have tested if array[i] != NULL to know if I need to fclose, but it's for the sake of the explanation ...)
You probably have to add another variable for the function return value.
I usually set this variable to indicate failure at the beginning (like setting false) and give it's success value just before the goto.
Sometime, in some situation, this can seem weird, but it's, in my opinion, still understandable (just add a comment :) )
I'd recommend you to read thoroughly the examples you have found (more if they are in the kernel code of an operating system.) The situation you describe corresponds to an algorithm that should make decisions at each stage of the execution, and those stages require to undo the previous steps.
You first allocate some resource #1, and continue.
then you allocate another resource (say resource #2) if that fails, then you have to free resource #1, as it is not longer valid.
...
finally you allocate resource #N, if that fails you must free resources #1 to #N-1.
The figure you show allows you to write in one line, a set of resource allocations, between which you have to decide if you continue.
In this scenario a policy like this is recommended (for novice C programmers, as it avoids the use of goto but becomes less readable (as it nests as things happen)
if ((res_1 = some_allocation(blablah)) != ERROR_CODE) {
if ((res_2 = some_other_allocation(blablatwo)) != ANOTHER_ERROR_CODE) {
...
if ((res_N = some_N_allocation(blablaN)) != NTH_ERROR_CODE) {
do_what_is_needed();
return_resource_N(res_N); /* free resN */
} else {
do_action_corresponding_to_failed_N(); /* error for failing N */
}
return_resource_N_minus_one(resN_1); /* free resN_1 */
...
} else {
do_action_corresponding_to_failed_2(); /* error for failing #2 */
}
return_resource_1(res1); /* free #1. (A): (see below) */
} else {
do_acttion_corresponding_to_failed_1(); /* error for failing #1 */
}
/* there's nothing to undo here, as we have returned the first resource in (A) above. */
nothing to say about this code, but that it has no gotos, but is incredible far less readable (it's a mess of nested things in which, when you fail for resource N, then you have to return up to N-1 resources.) you can messup the resources deallocated by putting them in the wrong position and it's error prone. But on the other side, it allocates and deallocates the things in just one place and is as compact as the code with gotos.
writing this code with gotos gives this:
if ((res_1 = some_allocation(blablah)) == ERROR_CODE) {
do_acttion_corresponding_to_failed_1(); /* error for failing #1 */
goto end;
}
if ((res_2 = some_other_allocation(blablatwo)) == ANOTHER_ERROR_CODE) {
do_action_corresponding_to_failed_2(); /* error for failing #2 */
goto res1;
}
...
if ((res_N = some_N_allocation(blablaN)) == NTH_ERROR_CODE) {
do_action_corresponding_to_failed_N(); /* error for failing #N */
goto resN1;
}
do_what_is_needed();
return_resource_N(res_N); /* free resN */
resN1: return_resource_N_minus_one(resN_1); /* free resN_1 */
...
res1: return_resource_1(res1); /* free #1. (A): (see below) */
end: /* there's nothing to undo here, as we have returned the first resource in (A) above. */
There's only thing that can be said about the first code that will make it perform better in some architectures. Dealing with goto is a pain for the compiler, as normally it has to make assumptions about all the possible resulting blocks that will end jumping to the same label, and this makes things far more difficult to optimice, resulting in not so optimiced code. (this is clear when you use structured blocks, and only implies one or two places you can come from), and you will get worse performance code (not much worse, but somewhat slower code)
You will agree with me that the equivalent code you post in your code is more readable, probably exactly the same level of correctness.
Other required use of goto constructs is when you have several nested loops and you have to exit more than the closest loop to exit.
for(...) {
for(...) {
...
for (...) {
goto out;
}
...
}
}
out:
this is also C specific, as other languages allow you to label the construct you want to exit from and specify it in the break statement.
E.g. in Java:
external_loop: for(...) {
for(...) {
...
for (...) {
break external_loop;
}
...
}
}
In this case you don't need to jump, as the break knows how many loops we need to exit.
One last thing to say. With just the while() construct, all other language constructs can be simulated, by introducing state variables to allow you to do things (e.g. stepping out of each loop by checking some variable used precisely for that). And even less.... if we allow for recursive function call, even the while() loop can be simulated, and optimicers are capable of guessing a faster implementation without recursion for the simulated block. Why in the schools nobody says never use if sentences, they are evil? This is because there's a frequent fact that newbies tend to learn one struct better than others and then, they get the vice of using it everywhere. This happens frequently with goto and not with others, more difficult to understand but easier to use, once they have been understood.
The use of goto for everything (this is the legacy of languages like assembler and early fortran) and maintaining that code normally ends in what is called spaghetti programming. A programmer just selects at random a place to write his/her code in the main code of a program, opens an editor and inserts it's code there:
Let's say that we have to do several steps, named A to F:
{
code_for_A();
code_for_B();
code_for_C();
code_for_D();
code_for_E();
code_for_F();
}
and later, some steps, named G and H have to be added to be executed at the end. Spaghetti programming can make the code end being something like this:
{
code_for_A();
code_for_B();
code_for_C(); /* programmer opened the editor in this place */
goto A;-------.
|
B:<---------------+-.
code_for_G(); | | /* the code is added in the middle of the file */
code_for_H(); | |
goto C;-------+-+--.
| | |
A:<---------------' | |
code_for_D(); | |
code_for_E(); | |
code_for_F(); | |
goto B; --------' |
|
C:<--------------------'
}
While this code is correct (it executes steps A to H in sequence), it will take a programmer some time to guess how the code flows from A to H, by following back and forward the gotos.
For an alternate open that can sometimes be used to "hide" the gotos, one of our programmers got us using what he calls "do once" loops. They look like this:
failed = true; // default to failure
do // once
{
if( fail == func1(parm1) )
{ // emit error
break;
}
failed = false; // we only succeed if we get all the way through
}while(0);
// do common cleanup
// additional failure handling and/or return success/fail result
Obviously, the if block inside the 'do once' would be repeated. For example, we like this structure for setting up a network connection because there are many steps that have the possibility of failure. This structure can get tricky to use if you need a switch or another loop embedded within, but it has proven to be a surprisingly handy way to deal with error detection and common cleanup for us.
If you hate it, don't use it. (smile) We like it.

Synchronizing the result of threads with incremented shared variable and condition

The title might not appear particularly clear, but the code explains itself:
int shared_variable;
int get_shared_variable() {
int result;
pthread_mutex_lock(&shared_variable_mutex);
result = shared_variable;
pthread_mutex_unlock(&shared_variable_mutex);
return result;
}
void* thread_routine(void *arg) {
while (get_shared_variable() < 5000) {
printf();
printf();
sleep(2);
int i = 0;
while (pthread_mutex_trylock(&foo_mutexes[i]) != 0) {
i++;
pthread_mutex_lock(&foo_count_mutex);
if (i == foo_count) {
pthread_mutex_unlock(&foo_count_mutex);
sleep(1); // wait one second and retry
i = 0;
}
pthread_mutex_unlock(&foo_count_mutex);
}
pthread_mutex_lock(&shared_variable_mutex);
shared_variable += 10;
pthread_mutex_unlock(&shared_variable_mutex);
}
return NULL;
}
I'm passing thread_routine to a pthread_create (pretty standard), but I'm having a problem with the synchronization of the result. Basically, the problem is that the first thread checks the while condition, it passes, and then another thread checks it, it passes too. However, when the first thread finishes and shared_variable reaches 5000, the second thread has not yet finished and it adds up another 10 and the end result becomes 5010 (or NUM_OF_THREADS - 1 * 10 if I run more than two) at the end, while the whole process should end at 5000.
Another issue is that in // do some work I output something on the screen, so the whole thing inside the loop should pretty much work as a transaction in database terms. I can't seem to figure out how to solve this problem, but I suppose there's something simple that I'm missing. Thanks in advance.
This answer may or may not be what you are after. Because as explained in the comments your description of the expected behaviour of the program is incomplete. Without the exact expected behaviour it is difficult to give a full answer. But since you ask, here is a possible structure of the program based on the code shown. The main principle it is illustrating is that the critical section for shared_variable needs to be both minimal and complete.
int shared_variable;
void* thread_routine(void *arg)
{
while (1) {
pthread_mutex_lock(&shared_variable_mutex);
if (shared_variable >= 5000) {
pthread_mutex_unlock(&shared_variable_mutex);
break;
}
shared_variable += 10;
pthread_mutex_unlock(&shared_variable_mutex);
/* Other code that doesn't use shared_variable goes here */
}
return NULL;
}

Function crashing in release mode but runs flawless in debugger

My program crashes on this function on the 7th line, when I call malloc() when I run in release mode I get the `Program.exe has stopped working message, and when I run in debugger, most of the time it succeeds but sometimes I get this message (especially on larger input):
MONOM* polynomialsProduct(MONOM* poly1, int size1, MONOM* poly2, int size2, int* productSize)
{
int i1, i2;
int phSize = 1, logSize = 0;
MONOM* product;
product = (MONOM*)malloc(phSize*sizeof(MONOM));
monomAllocationVerification(product);
for (i1 = 0; i1 < size1; i1++)
{
for (i2 = 0; i2 < size2; i2++)
{
if (logSize == phSize)
{
phSize *= 2;
product = (MONOM*)realloc(product,phSize*sizeof(MONOM));
monomAllocationVerification(product);
}
product[logSize].coefficient = poly1[i1].coefficient * poly2[i2].coefficient;
product[logSize].power = poly1[i1].power + poly2[i2].power;
logSize++;
}
}
mergeSort(product,logSize);
*productSize = sumMonomsWithSamePower(product, logSize);
return product;
}
I understand that I'm dealing with memory errors and problems, but is there any quick way to analyze my code and look for memory errors? I look at my code a dozen of times looking for this kind of errors and found nothing. (I didn't want to post the code here since its 420 lines long).
First of all, if heap corruption is detected on the first malloc, that means it happened earlier (not in this function or on previous pass). So the problem may lie outside this code.
However, the code also looks suspicious to me.
monomAllocationVerification has no size parameter, so it should work on one monom only, yet you call it only once after realloc on pointer to first element, despite having allocated space for quite a few monoms. Please clarify your decision.
It is a bit unclear why sumMonomsWithSamePower should return a size, and thus modify an array to store a value. May be a quirk, but still suspicious.
UPDATE
The problem was in other functions; a few reallocs with wrong size.
I would check the return value of malloc() and use perror() to describe what error has occured. Also here is the documentation for malloc() and perror().
if((product = (MONOM*)malloc(phSize*sizeof(MONOM))) == NULL)
{
perror("ERROR: Failed to malloc ");
return 1;
//perror() will display a system specified string to describe the error it may tell you the error
}
Also do you know the size of MONOM? If not add the following line to your code.
printf("MONOM SIZE = %i\n", sizeof(MONOM));

not declared in this scope creating a loop

I am tying to make a loop that repeats itself for 100 seconds, but I keep on getting the same error and I am getting so frustrated that even if it is the most basic thing I will not notice, could someone please tell me what I am doing wrong? I would really appreciate, thanks.
void loop(void) {
for ( int i = 0; i <= 100; i++) {
getFingerprintIDez();
delay (50)
}
}
uint8_t getFingerprintID() {
uint8_t attmpet = data.getImage();
switch (attempt) {
case FINGERPRINT_OK:
break;
case FINGERPRINT_NOFINGER:
Serial.println("No fingerprint detected");
return attempt;
delay (500);
}
attempt = data.image2Tz();
switch (attempt) {
case FINGERPRINT_OK:
Serial.println("Image converted");
break;
case FINGERPRINT_IMAGEMESS:
Serial.println("Image too messy");
return attempt;
}
attempt = data.fingerFastSearch();
if (attempt == FINGERPRINT_OK) {
Serial.println("Found a print match!");
} else if (attmpt == FINGERPRINT_NOTFOUND) {
Serial.println("Did not find a match");
return attempt;
}
Serial.print("Found ID #"); Serial.print(data.fingerID);
Serial.print(" with confidence of "); Serial.println(data.confidence);
return data.fingerID;
}
int getFingerprintIDez() {
uint8_t attempt = data.getImage();
if (attempt != FINGERPRINT_OK) return -1;
attempt = data.image2Tz();
if (attempt != FINGERPRINT_OK) return -1;
attempt = data.fingerFastSearch();
if (attempt != FINGERPRINT_OK) return -1;
Serial.print("Found ID #"); Serial.print(data.fingerID);
Serial.print(" with confidence of "); Serial.println(data.confidence);
return data.fingerID;
delay (1000);
}
The message I keep getting is:
exit status 1
'getFingerprintIDez' was not declared in this scope
Thank you all
In general, your indentation is a mess, and that's making it hard for you to see where the problem is. It looks to me like this line:
int getFingerprintIDez()
is a likely culprit for the error you're getting. I haven't counted braces, but I think your getFingerprintIDez() function might actually be defined inside the loop() function, and C doesn't allow that sort of thing.
So take care in formatting your code so that the various blocks are carefully indented the right amount -- C doesn't care about indentation, but it'll make it easier for you to see what blocks are inside what other blocks. Count open and close braces if you need to, and make sure that the definition of loop() ends before the definition of getFingerprintIDez() begins.
missing ; after delay(50)
unused variable 'attmpet'
'attmpt' was not declared in this scope
read the error messages from the first, not the last. the last error is only a consequence of the previous errors

Resources