-1

I'm currently writing an assignment that requires adding new system calls to the kernel, and I've encountered a weird problem when writing system calls tests in C.

In one of the tests, I compare a return value from a system call to the value 1, and the if statement fails even though the syscall returns 1.

The MACRO that's used for comparison:

#define CHECK(expr,expected) \
    if ((expected) !=(expr)) {\
    printf("\nCheck failed (%s:%d).\n", __FILE__, __LINE__); \
    printf("Expected: %d, got: %d\n", expected, expr);\
    test_failed = 1; \
}

The line that fails from the test:

CHECK(unblock_program(strings[PROG_A], lengths[PROG_A]), 1);

I'm running the test on linux-2.4.18-14.

Caesar23
  • 99
  • 7
  • Error in the line 33, i am pretty sure. – Maxim Egorushkin Apr 07 '16 at 15:00
  • if i remind well, the syscall return value is in errno. – Pierre Emmanuel Lallemant Apr 07 '16 at 15:00
  • The brackets don't match. – Martin James Apr 07 '16 at 15:00
  • MartinJames - They do match. MaximEgorushkin - You're not helpful. – Caesar23 Apr 07 '16 at 15:07
  • @Caesar23: no it has to return 0. – Pierre Emmanuel Lallemant Apr 07 '16 at 15:09
  • @PierreEmmanuelLallemant the return value is implementation dependent. I've chosen to return 1, since it checks for containment in an internal data structure. – Caesar23 Apr 07 '16 at 15:11
  • Should the 'if' block not have a curly bracket to close it? – Martin James Apr 07 '16 at 15:11
  • The closing curly bracket is in the last line. Besides, you're not focusing on the main topic of this post, which is the if statement fails even though both values are 1. – Caesar23 Apr 07 '16 at 15:13
  • @Caesar23 OK, I see it now. Something went awry with the rendering on my browser:( I had to refresh to see the last line. – Martin James Apr 07 '16 at 15:15
  • First question - are you calling it as `CHECK(syscall, 1)` or `CHECK(syscall(), 1)`? If the former, that might explain what you're seeing. What happens when you call it as `CHECK(1, 1)`? – John Bode Apr 07 '16 at 15:16
  • 'Show where you call it' was going to be my next comment. – Martin James Apr 07 '16 at 15:17
  • I calling it as CHECK(syscall(...), 1). You can see the code above. and calling CHECK(1, 1) works fine. – Caesar23 Apr 07 '16 at 15:17
  • ..speedily followed by 'what happens when you run it under your debugger? – Martin James Apr 07 '16 at 15:18
  • I've never used the debugger to be honest. I've been debugging by printing so far. – Caesar23 Apr 07 '16 at 15:19
  • @Caesar23: Yeah, I refreshed your edit immediately after writing my comment. Next suggestion would be to look at a listing with the macro expanded out (i.e., after `gcc -E` or similar). – John Bode Apr 07 '16 at 15:19
  • ..and 'what happens when you load the returned value from 'unblock_program()' inot a temp var before the macro? – Martin James Apr 07 '16 at 15:20
  • Yeah, I just realized, the syscall is being executed multiple times in that macro. That could be part of the problem right there. – John Bode Apr 07 '16 at 15:21
  • 'I've never used the debugger to be honest.' - well, if you're adding syscalls, it's about time you learned how to use your debugger! – Martin James Apr 07 '16 at 15:21
  • @JohnBode How so ? – Caesar23 Apr 07 '16 at 15:22
  • @JohnBode ,,which is why OP should (a) always check out the post-preprocessing code after the expansion and (b) stop using macros at all, – Martin James Apr 07 '16 at 15:23
  • @JohnBode You're right !, in printf I'm calling the syscall again. Actually my partner wrote the test not me. Thank you ! – Caesar23 Apr 07 '16 at 15:24
  • 2
    @Caesar23: Your macro expands out to `if (syscall() != 1) { printf ("%d", syscall()); }`; it's possible that the first call is returning something other than 1, but the second call returns 1. – John Bode Apr 07 '16 at 15:24
  • @Caesar23 think about how macros work - they are NOT function calls. – Martin James Apr 07 '16 at 15:24
  • @Caesar23 are you in a position to fire your partner? – Martin James Apr 07 '16 at 15:25
  • @MartinJames Relax man. It's a homework assignment for a course that I'm taking this semester. And thanks everyone. – Caesar23 Apr 07 '16 at 15:27
  • And learn how to use your debugger! If you had stepped though the macro call/expansion, you would have seen the multiple calls to 'unblock_program()', avoided all the confusion, avoided an SO post, got the answer quicker and been able to fire your partner earlier:) – Martin James Apr 07 '16 at 15:27
  • 1
    @Caesar23: If you're committed to using a macro, I suggest you do something like this: `#define CHECK(expr,expect) do { int tmp = expr; if ( tmp != (expect) { ... } } while (0)`. This way you execute `expr` only once. TBH, though, I'd junk the macro and make it a full-fledged function (declared `inline`, if possible). – John Bode Apr 07 '16 at 15:28
  • Some might say that, if you're committed to using a macro, you should be committed. I couldn't possibly comment... – Martin James Apr 07 '16 at 15:29
  • all this talk got me thinking of the difference between macros and inline functions: http://www.programmerinterview.com/index.php/c-cplusplus/inline-vs-macro/ http://stackoverflow.com/questions/1137575/inline-functions-vs-preprocessor-macros – yano Apr 07 '16 at 15:29

1 Answers1

1

A syscall returns -1 if there is an error.

You have to check the value of errno which contains the return value of your syscall.

When the syscall is successful, it has to return 0, not 1.