CS360 Final Exam: May 11, 2010 - James S. Plank

Answer all questions.

Question 1

You receive the following email:

"Hello Sir, I was going through setjmp. I came across your nice article http://web.eecs.utk.edu/~jplank/plank/classes/cs360/360/notes/Setjmp/lecture.html. I tried some things with setjmp. But with the attached program (compiled on GCC 4.4.1 in Ubuntu 9.10), I found that the code crashes due to SIGSEGV. Could you please help me in understanding why it results in a segmentation fault? Am I doing something that I am not supposed to do? Thanks in advance for your help. Thanks and regards, Waluigi....."

While you do don't get paid to help people like Waluigi, you feel it is rude to ignore him, so you look at his program:

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

jmp_buf buf;
void g(int n);
void h(int n);
int n = 6;

static int counter = 3;

void f(void)
{
    int x[n]; // valid: f is not terminated
    printf("Entered function = f\n");
    g(n); //this gets it core dumping
    printf("Value returned by setjmp = %d\n",setjmp(buf));
    g(n);
    printf("Exiting function = f\n");
}

void g(int n)
{
    int a[n]; // a may remain allocated
    printf("Entered function = g\n");
    h(n);
    printf("Exiting function = g\n");
}

void h(int n)
{
    int b[n]; // b may remain allocated
    printf("Entered function = h\n");
    if(--counter > 0)
    longjmp(buf, 4); // might cause memory loss
    printf("Exiting function = h\n");
}

int main (int argc, char *argv[])
{
   f();
   return EXIT_SUCCESS;
}

We won't recount the ways in which Waluigi's program makes you feel ill. After taking an aspirin, you scan the program and figure out why it segfaults. Explain to me why it has a segmentation violation and what the output will be before the segfault. Be precise about why it segfaults.

----------------------------------------------------------------------------------------------------------------

Question 2

Write the unoptimized assembly code for the following C procedure:

int cproc(int **x)
{
  int y;

  y = b(x[15], 7);
  return y+3;
}

Question 3

Assume that malloc() and free() are implemented as described in class. The following procedure b() has a bug in it:

void b()
{
  int *x;
  int i;

  x = (int *) malloc(sizeof(int) * 10);
  printf("0x%x\n", x);
  for (i = 0; i < 10; i++) {
    *x = i*40;
    x++;
  }
  free(x);
}

Question 4

Write a program that generates SIGPIPE. You are not allowed to use the kill program, the kill() system call, the system() program or any shell scripts -- just write a C program that generates SIGPIPE.

Question 5

Explain exactly what happens when you call execv (or any of the variants of execve). Be as precise as you can be.

Question 6

The following code creates n threads which run the procedure thread(). Your job is to add code to this program that guarantees that no thread runs do_more_random_stuff() until all n threads have finished running do_random_stuff(). You are only allowed to add code at the four places maked "Your Code Here." You are not allowed to use sleep() or do any busy waiting.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

typedef struct {
  int id;
  int n;
  pthread_t tid;
  /* Your Code Here: A */
} Thread_Info;

void *thread(void *arg)
{
  Thread_Info *ti;

  ti = (Thread_Info *) arg;
  do_random_stuff(ti);

  /* Your Code Here: B */

  do_more_random_stuff(ti);
}

main(int argc, char **argv)
{
  Thread_Info *ti;
  int i;
  int n;

  /* Your Code Here: C */

  n = atoi(argv[1]); 

  for (i = 0; i < n; i++) {
    ti = (Thread_Info *) malloc(sizeof(Thread_Info));
    ti->id = i;
    ti->n = n;

    /* Your Code Here: D */

    pthread_create(&(ti->tid), NULL, thread, (void *) ti);
  }

  pthread_exit(NULL);
}

You are only allowed to use the following thread calls:

int  pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
int  pthread_cond_signal(pthread_cond_t *cond);
int  pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int  pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
int  pthread_detach(pthread_t thread);
int  pthread_join(pthread_t thread, void **value_ptr);
int  pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
int  pthread_mutex_lock(pthread_mutex_t *mutex);
int  pthread_mutex_unlock(pthread_mutex_t *mutex);
void pthread_exit(void *value_ptr);

Question 7

Behold the following C program:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

main()
{
  int fd1, fd2, fd3, fd4, i;
  char buf[10];

  fd1 = open("f1.txt", O_RDONLY);
  fd2 = open("f2.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
  fd3 = open("f3.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);
  
  fd4 = dup(0);
  dup2(fd1, 0);
  dup2(fd2, 1);

  i = read(fd1, buf, 9);  if (i < 0) exit(0);
  write(fd2, buf, i);

  i = read(0, buf, 9);  if (i < 0) exit(0);
  write(1, buf, i);

  i = read(fd4, buf, 9);  if (i < 0) exit(0);
  write(fd3, buf, i);

  dup2(fd4, 0);
  close(fd1); close(fd2); close(fd3); close(fd4);

  scanf("%d", &i);
  printf("%d\n", i);
  exit(0);
}

I compile the program into an executable called a.out, and I have the following input files:

f1.txt
12341234 23452345 34563456 45674567
f4.txt
98765432 97531864 13579246 14703692

Tell me the output of the following three commands (executed in this order). If there is a segmentation violation, or the program aborts due to an error, include that in your output.

UNIX> ./a.out < f4.txt

UNIX> cat f2.txt

UNIX> cat f3.txt