XML

kent logo

CO527 Anonymous Questions and Answers

This page lists the various questions and answers. To submit a question, use the anonymous questions page. You may find the keyword index and/or top-level index useful for locating past questions and answers.

We have taken the liberty of making some minor typographical corrections to some of the questions as originally put. Although most of the questions here will have been submitted anonymously, this page also serves to answer some questions of general interest to those on the course.


Question 61:

I have 2 questions:

  1. I don't understand this bit in your answer to an earlier question (Question 18 (2003)):

        if (current.signalled) {
            wait_queue.del_from_queue (current);
            // abort and return with EINTR (interrupted)
        }
    

    What's all this about aborting? Does it need to be done for the `MMailBox' class ? Also, does the code in the above if statement handle the aborting bit or is it code that has to be added ?

  2. When a process wakes up, how can we make it check for its new messages ? Would it be done by doing some thing like this in `recvmsg' ?:

        public static Object recvmsg(...) {
            // Scan the list and return a message if available
            // If not, send the process to sleep
            // (when process wakes up) make a recursive call to recvmsg
        }
    

Answer 61:

  1. The comment that refers to `aborting' means: perform any additional local cleanup, e.g. undo things we did before going to sleep. In many cases, the only `undo' action that needs to be performed is the removal of the process from the `MWaitQueue' on which it was blocked (and is probably still on). The key thing is that it did not wake up as a result of your `sendmsg()' code, so you won't have removed it from the `MWaitQueue' yet (hence the `del_from_queue()' call to remove a specific process).

    You don't have to do this for your own `MMailBox' class, but you will likely get more marks if you do.. However, you should aim to understand what is going on, rather than simply shoving in code -- things can go very wrong with this sort of code if mis-programmed (in the context of operating-systems). For the single virtual-CPU MOSS, and the way the test programs are written, things are not likely to go wrong. The only slightly dubious case is when `UMailSend' terminates whilst `UMailRecv' is blocked in `recvmsg()'. In this situation, the sleeping `UMailRecv' will be woken as the result of receiving the SIGCHLD signal. You can prevent this from happening, if you wish, by getting `UMailRecv' to ignore the signal. To do this, add the following line to `UMailRecv', somewhere before the call to `MPosixIf.forkexecc()'.:

        MPosixIf.signal (MSignal.SIGCHLD, MSignal.SIG_IGN);
    
  2. You are effectively correct. A recursive implementation, however, would not be advised. On the positive side, though, what you have here is something generally known in the computer-science world as `tail-call recursion' -- i.e. the recursive call is the last thing to happen in the function/method. This has a more efficient equivalent:

        public static Object recvmsg(...) {
            while (true) {
                // Scan the list and return a message if available
                // If not, send the process to sleep
            }
        }
    

    Some compilers will automatically do this type of (tail-call) optimisation, but it's not something you should rely on. Besides, optimising programmers are generally more effective than optimising compilers (at the program-structure level)..

Keywords: moss , signal , mailbox

Referrers: Question 64 (2003) , Question 69 (2003) , Question 71 (2003) , Question 77 (2003)


Question 62:

How can I create a `MailMessage' object and modify its fields? It's a `static' class, but in `MailMessage', the fields are non-static. Therefore I have a problem changing the values. Should I put more methods in the class?

Answer 62:

Although the class itself is static, you can still create instances (objects) of it. Once you've got an instance, just assign to the fields directly. For example:

    MailMessage msg = new MailMessage ();

    msg.from_pid = ...;
    msg.to_pid = ...;

The reason the class has to be declared `static' is explained a bit in the answer to Question 11 (2003).

Keywords: moss , mailbox

Referrers: Question 67 (2003) , Question 67 (2003)


Question 63:

What should `recvmsg()' in `MPosixIf' return ? An `Object' ? Also should the two added methods in `MPosixIf' have parameters ? Thank you.

Answer 63:

Yes, `recvmsg()' should return an `Object'. That `Object' is the `message', sent by a call to `sendmsg()'. See the answer to Question 10 (2003) for more information on this. The two methods you add to `MPosixIf' should indeed have parameters -- those given on the assessment description sheet. E.g., in `MPosixIf':

    public static int sendmsg (int pid, int type, Object message)
    {
        // your code here
    }

    public static Object recvmsg (int pid, int type)
    {
        // your code here
    }

You need to fill in the bodies for these methods. However, the real code for sending/receiving should be in a separate class (e.g. `MMailbox'), which the methods in `MPosixIf' call.

Keywords: moss , mailbox


Question 64:

I'm trying to get my head around your reply to Question 61 (2003), part 1. What you have said makes some sense to me but I could use further clarification.

    if (current.signalled) {
        wait_queue.del_from_queue (current);
        // abort and return with EINTR (interrupted)
    }
"The key thing is that it did not wake up as a result of your `sendmsg()'' code, so you won't have removed it from the `MWaitQueue' yet (hence the `del_from_queue()'' call to remove a specific process)."

So are you saying that if the body of the `if' statement above is reached (i.e. the `del_from_queue()' method call) that something has gone wrong (becasue it didn't wake up as a result of `sendmsg()' ?

"The only slightly dubious case is when `UMailSend' terminates whilst `UMailRecv' is blocked in `recvmsg()'. In this situation, the sleeping `UMailRecv' will be woken as the result of receiving the SIGCHLD signal. You can prevent this from happening, if you wish, by getting `UMailRecv'' to ignore the signal. To do this, add the following line to ``UMailRecv', somewhere before the call to `MPosixIf.forkexecc()'.:
``MPosixIf.signal (MSignal.SIGCHLD, MSignal.SIG_IGN);''

Why would you want to ignore the signal ? Wouldn't that leave the process blocked for all eternity ? I thought the idea of sending the signal to `UMailRecv' was to wake it up, because no other (user) process was going to tell it to (and presumably hope that it will handle the situation appropriately). Did you simply suggest this as an alternative to implementing better approach (possibly such a s the one I outline below).

If the `dubious case' occured, wouldnt it be best to simply delete it from the local queue and report an error by returning null ? Is there anything I missed ?

Answer 64:

If the body of the `if' is reached in the above code, then something has not gone wrong, as such. It means that the process was signalled -- which might be for various reasons. SIGCHLD is the signal indicating that a child-process has terminated (or been `TASK_STOPPED').

You might want to ignore SIGCHLD because you might not be interested in knowing about your child processes terminating -- depends on the application. For `UMailRecv', knowing about the termination of child processes isn't important. It might leave the process blocked for eternity, at least until a message is sent to it, or another non-ignored signal is delivered.

Yes, in the `dubious' case, it's best to handle it properly, by checking for `current.signalled' and removing it from the wait-queue and returning an error (`null') if so.

Keywords: moss

Referrers: Question 74 (2003)


Question 65:

  1. I'm not sure where the `pid' param comes into play.. Is it only needed when it is `-1' so that any stored messasge can be returned ? When I check for stored messages I am using the `pid' of the current process.

  2. Where does the `type' param need to be used ? Should I only return messages of a certain `type' ? (say if the `pid' was a match but the `type' was not then `null' would be returned). If that is the case then I take it that `-1' means any type of message is ok.

Answer 65:

  1. The `pid' parameter for `sendmsg()' gives the destination process ID. The `pid' parameter for `recvmsg()', if not -1, indicates that a message should be received from that specific process. Thus `recvmsg' must always match message destination (the invoking process's PID equal to the message's `to_pid'). Additionally, if the user-supplied `pid' is not -1, then that PID must match the message's `from_pid'. If the supplied `pid' is -1 then the user-process doesn't care which other process sent it a message.

  2. The logic of the `pid' parameter for `recvmsg()' (described in (1)) applies to the `type' parameter too. If the supplied `type' is not -1, then that `type' must match the message's `type'. If the supplied `type' is -1, then the message's type can be anything (i.e. the user-process doesn't care).

    If the match fails (e.g. there are messages for the process, but not ones that match `pid' and/or `type'), then the process should block -- just as if there were no messages for that process.

Keywords: moss , process-id , mailbox

Referrers: Question 77 (2003)


Question 66:

I'm a bit baffled as how to go about blocking processes in the `mailbox' (1b) implementation. If you could summarise it, and the built-in parts of MOSS to use, that would be great. So far I have set up a second `ArrayList' to use as the queue. Thanks.

Answer 66:

Firstly, for holding blocked processes, use an `MWaitQueue'. This is mostly standard DIY linked-list code. The `q_next' field in `MProcess' (see the Javadoc output) is used to link processes when on the `MWaitQueue'. Using an `ArrayList' is, in many ways, fine too. The point of using the `MWaitQueue' is that it explicitly identifies (abstracts) `blocked processes' -- an `ArrayList' can hold anything.

The (mostly) basic code for putting a process to sleep is given in the answer to Question 18 (2003). The general logic is this (`process' refers to the `current' process):

A fairly complex example of putting a process to sleep can be seen in `MPipe.java's `read()' and `write()' methods. Similar code for a `mailbox' should be simpler, however.

Keywords: moss , sleeping

Referrers: Question 69 (2003) , Question 85 (2003) , Question 87 (2003)


Question 67:

When I program the code which you suggest in the answer to Question 62 (2003), I get a 'NoClassDefFoundError' when I run the mail-test.

Could you give some tips on how to fix this problem ?

Answer 67:

Do you really mean Question 62 (2003) ..? I can't really offer any help without seeing more of the error -- in particular, which class is not found.

It might be worth manually deleting all the `.class' files then re-compiling everything. If you're using Bluej, hit the compile button, etc. -- but make sure that the two mail-test classes `UMailRecv' and `UMailSend' are there too. If you're compiling from a UN*X command-prompt using the supplied `Makefile', do the usual ``make'' then ``make modules'' -- you'll need to have added `UMailSend.class' and `UMailRecv.class' to the `Makefile' (where-abouts should be mostly obvious).

Keywords: moss


Question 68:

When running `UMailRecv' to test my mail-box, sometimes it will work, but most of the time it will do nothing.

Answer 68:

Sounds like a bug. The difference is possibly due to the scheduling order of processes. I.e. whether `UMailSend' or `UMailRecv' communicates first. Putting in some debugging code (print statements) might help -- you can use ``System.err.println(..)'' for debugging quite effectively (or use a proper debugger).

Keywords: moss , mailbox


Question 69:

For the mail-box, if I want to send a message, do I first delete the process from the `MWaitQueue' that I want to send to ?; and for the receive process, if there is not a message, do I just add it to the `MWaitQueue' and set the state to sleeping ?

Answer 69:

For receiving, if there are no messages for the process, then yes, it should be put to sleep (using an `MWaitQueue') -- see the answers to Question 18 (2003) and Question 66 (2003) for information on putting a process to sleep (blocking it).

When sending a message, if there is a blocked process waiting for the message, then it should be woken up -- removed from the `MWaitQueue' and then added to the run-queue (using ``MKernel.add_to_run_queue()'') -- the answer to Question 18 (2003) gives an example of this.

One problem is identifying (in `sendmsg()'), which particular process needs to be woken up, as the `MWaitQueue' only holds processes -- it does not hold the extra information needed to determine whether the message being sent can be received (that information is effectively the `recvmsg()' `pid' and `type' parameters. One way to deal with this is not to save the `recvmsg()' parameter information, but to wake up all blocked processes when any message is sent. The woken receivers can then scan the message-queue again, and go back to sleep if no messages have arrived. See the answer to Question 61 (2003) (part 2) for some related information on this.

Keywords: moss , mailbox


Question 70:

When I run `UMailRecv', with `System.out' messages in my code to show messages sent and received, I get:

    MOSS# run UMailRecv
    process started, PID 3
    UMailRecv -- mail-box receiver process
    UMailRecv: started message sender, pid 4
    UMailSend -- mail-box sender process
    UMailSend: sending sleepy messages to PID 3...
    from = 4 to = 3 type = 0 msg = null
    from = 4 to = 3 type = 0 msg = null
    from = 4 to = 3 type = 0 msg = null
    from = 4 to = 3 type = 0 msg = null
    UMailSend: done.  exiting.
    UMailRecv: MPosixIf.recvmsg() returned null! -- retry..
    from = 4 to = 3 type = 0 msg = null

For the `sendmsg()' I am not passing a `null' parameter, I am using the parameter used by `UMailSend' but the message `Object' is sent as `null'.

Answer 70:

The problem here looks like broken parameter handling. `UMailSend' does not send `null' messages; and the `type' is not always 0 -- each of the four test messages (just `String's) is sent with a different `type' -- look at the code in `UMailSend.java' !

It'd be worth adding more debugging statements -- in the code you add to `MPosixIf' and in your specific `MMailBox' class. This should hopefully reveal the error. It's also worth double-checking the debugging lines to make sure they're actually reporting the parameters (and not a local variable, etc.).

Keywords: moss , mailbox


Question 71:

I am trying to implement an elegant waking solution for sleeping processes on the mailbox option. Given that a process is suspended when it requests a message and there are none waiting, when it wakes up I assume it continues executing `recvmsg()'. In my solution I am waking all processes on the queue when a message is recieved, so a process may or may not have a message waiting.

Recursively calling `recvmsg()' seems the ideal solution, but I'm not sure it's robust. Is there a stack limit for recursion: will there be problems if a process is continually suspended and resumed?

The alternative seems to be to return `null'' and hope that the process will re-request the message, though this gives different output from `UMailRecv' I am not sure is correct.

Answer 71:

Waking all the blocked processes is fine -- perhaps not an ideal solution, but the alternatives are messy.

Recursively calling `recvmsg()' is not a good idea, as you suspect. There is a limit on recursion, but it depends on all sorts of things which MOSS can't control (JVM and stack depth). Returning `null' in this case isn't a good idea either -- the specification says that `null' should be used to report an error, which wouldn't be the case. The `UMailRecv' program will `retry' a couple of times if `null' is returned -- mainly in the interests of being slightly robust (e.g. if the `recvmsg()' call was interrupted by a signal).

The solution (in code) is much simpler, however! The recursion you want to add to `recvmsg()' is of a particular type (or can be made into that form) -- tail-call recursion. This has a `loop' equivalent, that is much more stack-friendly. See the answer to Question 61 (2003) (part 2).

Keywords: moss , mailbox , sleeping

Referrers: Question 74 (2003)


Question 72:

How do we hand in our work? Through raptor, or by email ?

Answer 72:

I recently posted to the .cs2 newsgroup about this. You should submit your code using the submission directories on raptor, in:

    /usr/local/proj/co501/assignment3/your-login/

or from windows:

    \\raptor\files\proj\co501\assignment3\your-login\

replacing `your-login' with, um, your login. Either submit only the files you changed, or the whole lot -- I'll prune away unchanged files before marking.

Keywords: moss , submission

Referrers: Question 103 (2003)


Question 73:

I think I have completed the project, but am not completely sure if I have completed everything that is required.

I have added the methods to `MPosixIf'.

Could you tell me if there is anything else that I should be doing?

    [snip MMailBox code]

Answer 73:

This sort of question is better asked by email. However, after looking at your code, there are two things which need slight attention. Firstly, a process may have many messages waiting for it -- your code appears to allow only one message per process. Secondly, when no messages are available (in `recvmsg()'), the current process should be put to sleep (descheduled) until a message for it is available. See the answer to question Question 18 (2003) for information on putting a process to sleep.


Question 74:

For the Mail Box option..

I am unsure where and when to actually do things such as blocking the current process, adding it to the queue and waking processes up again. Are all three done within `recvmsg()' ? If the current process is blocked or put to sleep should `null' be returned after this if there is no suitable message to return? Should every call of `recvmsg()' result in a process being added to the queue? I'm ok with the code just not the general order in which everything needs to be done.

Also assuming that my code is correct, what is the maximum percentage that can be achieved without doing any of the above? (blocking, sending to sleep, adding to queue)

Thanks for your help.

Answer 74:

The answers to questions Question 18 (2003) and Question 71 (2003) should give some insight. The `recvmsg()' code should perform the `queue' and `block' (deschedule) operations. `sendmsg()' should reschedule the blocked process (by adding it to the run-queue).

In response to your second point, not quite; the `recvmsg()' method should not return `null' if the process blocked, woke up again, and there are no messages available -- it should go back to sleep again. However, if the blocked process woke up as a result of being signalled, then `null' should be returned (without removing any messages from the message-queue). Handling the signalling isn't too hard -- see the answers to Question 18 (2003) and Question 64 (2003).

Whether `recvmsg()' `blocks' depends on whether there are any messages waiting. If a message can be retrieved, then it is. If not, then the process should be blocked.

Without the blocking aspect of message-passing, I would expect the maximum attainable mark to be less than 70%. The marking scheme hasn't been finalised yet, though.

Keywords: moss


Question 75:

How do the two mail-box test programs interact with each other, with respect to blocking ?

Answer 75:

Below is a diagram showing a possible sequence of actions taken by the `UMailRecv', `UMailSend' processes, and your own code (in `MMailBox' interfaced through `MPosixIf'). Hopefully this will show, more clearly, how the blocking aspect of the mailbox should work (it also applies to some of the other blocking-involved options).

Keywords: moss , mailbox , sleeping , gfx

Referrers: Question 85 (2003) , Question 87 (2003)


Question 76:

In response to Question 34 (2003) and Question 35 (2003), you mention that students have a knowledge of C, this isn't true for all degree programmes, though, such as CSMS, CSBA and european-CS. Java isn't required that much in these programmes which makes it all the more difficult when a `hard' assessment is set, and students haven't been doing the general smaller assesments in Java that straight CS students undertake. Hope this point can be considered for future assessments, however its too late for this year!

Answer 76:

Your point about the non-straight-CS programmes not requiring as much Java (or other programming) is valid. I may take this into account when marking, however, finding a solution which everyone is happy with might be difficult (other than offering an `easier' option for less marks). I will take this into account for future years, however.

Keywords: moss


Question 77:

Hi,

This is for question 1(b); I'm getting this error when I run UMailRecv:

    MOSS# run UMailRecv
    process started, PID 3
    UMailRecv -- mail-box receiver process
    UMailRecv: started message sender, pid 4
    UMailSend -- mail-box sender process
    UMailSend: sending sleepy messages to PID 3...
    java.lang.NullPointerException
        at MKernel.add_to_run_queue(MKernel.java:337)
        ...

It tells me that `MMailBox.sendmsg()' is referencing a `null' list I guess.

I wasn't entirely sure as to what to do in `sendmsg()' for the blocking but I've got this from an anonymous question:

    {
        MProcess other;

        // get process from queue
        other = blocked.get_from_queue ();

        // add it to the run-queue for scheduling
        MKernel.add_to_run_queue (other);
    }

The last line is causing the `NullPointerException', so I'm guessing that it wasn't able to get any processes from the queue.

I'm not sure why this is happening because I think I'm adding them properly in `recvmsg()' (followed Question 18 (2003) and Question 61 (2003)):

    [snip code]

Can you tell me what I'm doing wrong in adding to my `MWaitQueue' ?

Thanks in advance.

Answer 77:

I suspect the problem is in your `sendmsg()' code, rather than the `recvmsg()' code (that looks mostly fine [1]). Before you remove a process from the `MWaitQueue', you should check that it is not empty, using the `is_empty()' method on the `MWaitQueue'. Alternatively, check that `other' is not `null' before calling `MKernel.add_to_run_queue()'.

The reason the `MWaitQueue' is empty is most likely because the receiving process hasn't called `recvmsg()' yet.

[1]. Your test for the `type' in `recvmsg()' is fine, but the test for the `pid' is not quite right. The `pid' argument here refers to the process ID of the sending process; -1 does not mean ``receive a message sent by anyone to anyone''. The logic of the `if' expression isn't quite right -- see the answer to question Question 65 (2003).

Keywords: moss

Referrers: Question 78 (2003)


Question 78:

If you haven't answered them yet, you can disregard the questions about the `NullPointer' and the `ClassCast' exceptions (I've fixed those.. for the `ClassCast' I wasn't returning the `message', and for the `NullPointer' I was doing something wrong in `sendmsg ()').. sorry about those.

I've now somewhat gotten it to work but now this happens:

    MOSS# run UMailRecv
    process started, PID 3
    UMailRecv -- mail-box receiver process
    UMailRecv: started message sender, pid 4
    UMailSend -- mail-box sender process
    UMailSend: sending sleepy messages to PID 3...
    UMailRecv: got message [Hello, mailbox world 0 :)]
    UMailRecv: got message [Hello, mailbox world 0 :)]
    UMailRecv: got message [Hello, mailbox world 0 :)]
    UMailSend: done.  exiting.
    UMailRecv: got message [Hello, mailbox world 3 :)]
    child exited with code 0

I'm not sure why I'm receiving message 0 three times and 1 and 2 none at all. Any ideas on what I might be doing wrong ?

thanks in advance.

Answer 78:

I'd already answered the question relating to your `NullPointer' exception (Question 77 (2003)). The `ClassCast' question didn't get answered, though.

For this particular problem, check that you're removing the right message from the message-queue. Once a message has been `recvmsg()'d, it should not appear again.

Keywords: moss , mailbox


Question 79:

I've almost got the `MMailBox' implementation to work, but I think there's a problem with my `recvmsg()'.

When running the test I get:

process started, PID 3
UMailRecv -- mail-box receiver process
UMailRecv: started message sender, pid 4
UMailSend -- mail-box sender process
UMailSend: sending sleepy messages to PID 3...
UMailRecv: got message [Hello, mailbox world 0 :)]
UMailRecv: got message [Hello, mailbox world 1 :)]
UMailRecv: got message [Hello, mailbox world 0 :)]
UMailSend: done.  exiting.
UMailRecv: got message [Hello, mailbox world 3 :)]
child exited with code 0

Do you know what could be causing this ?

Also, from Question 18 (2003), when putting the process to sleep you return `EINTR' if `current.signalled':

if (current.signalled) {
   wait_queue.del_from_queue (current);
   // abort and return with EINTR
}

Do we need to return this for the `MMailBox' ? as an `int' can't be returned.

Answer 79:

The problem is most likely being caused by incorrect removal of messages from the message-queue. Check your code for that carefully.

For the `Object' returning `recvmsg()' method, return `null' to indicate that the process was interrupted by a signal.

Keywords: moss , mailbox


Question 80:

Hi, my mail-box seems to send the 4 messages, but will only receive the first message sent.

Answer 80:

How do you mean ? -- that the first message is received 4 times, or that the first message is received then the thing freezes/fails ? It would have been useful to include the test-program's output.

Keywords: moss , mailbox

Referrers: Question 91 (2003)

Valid CSS!

Valid XHTML 1.0!

Maintained by Fred Barnes, last modified Thu May 8 12:58:05 2014