[Django] #16682: KeyboardInterrupt not handled properly in transaction aborting

43 views
Skip to first unread message

Django

unread,
Aug 23, 2011, 6:43:58 AM8/23/11
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: mtredinnick | Owner: nobody
Type: Bug | Status: new
Milestone: | Component: Database
Version: 1.3 | layer (models, ORM)
Keywords: | Severity: Normal
Has patch: 0 | Triage Stage:
Needs tests: 0 | Unreviewed
Easy pickings: 0 | Needs documentation: 0
| Patch needs improvement: 0
| UI/UX: 0
-------------------------------------+-------------------------------------
Ticket #6928 was reopened to report this, so I (Malcolm) am moving it to a
new ticket, since it's a separate issue. Following text is from comment:7
on that ticket:

---

After [14288] transaction.commit_on_success does not handle
`KeyboardInterrupt`.

Problem in `django.db.transaction.Transaction.__exit__` and default
`exiting` function.

{{{#!python
def __exit__(self, exc_type, exc_value, traceback):
self.exiting(exc_value, self.using)
}}}

`exc_value` is None after `KeyboardInterrupt` has been throwed, only
`exc_type` and `traceback` has value.
But if raise `KeyboardInterrupt` manualy from code it's work ok.

Possible solution: use `exc_type` and `exc_value` in `exiting` function

I use python 2.6.6

--
Ticket URL: <https://code.djangoproject.com/ticket/16682>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Aug 25, 2011, 12:07:37 PM8/25/11
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: | Owner: nobody
mtredinnick | Status: closed
Type: Bug | Component: Database layer
Milestone: | (models, ORM)
Version: 1.3 | Severity: Normal
Resolution: needsinfo | Keywords:
Triage Stage: | Has patch: 0
Unreviewed | Needs tests: 0
Needs documentation: 0 | Easy pickings: 0
Patch needs improvement: 0 |
UI/UX: 0 |
-------------------------------------+-------------------------------------
Changes (by aaugustin):

* status: new => closed
* resolution: => needsinfo


Comment:

I'm sorry, but this report doesn't contain enough information to reproduce
the problem. How can you get a `KeyboardInterrupt` within
`transaction.commit_on_success`?

I wrote this test code:
{{{
# models.py

from django.db import models

class FooModel(models.Model):
foo = models.CharField(max_length=42)

# views.py

import time
from django.db import transaction
from .models import FooModel

@transaction.commit_on_success
def interrupt_me(request):
FooModel.objects.create(foo='foo')
print "Hit Ctrl-C now!"
time.sleep(5)
print "Too late, and I didn't bother to return a HttpResponse"
}}}
and hooked the view in the URLconf.

Then I ran: `./manage.py runserver --traceback`

I open the URL in a browser, and during the sleep, I hit Ctrl-C in the
console. `runserver` exits cleanly, with or without
`transaction.commit_on_success`.

Please provide a test case or instructions to reproduce your problem and
re-open the ticket.

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:1>

Django

unread,
Aug 31, 2011, 1:16:44 AM8/31/11
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-----------------------------------------+-------------------------------
Reporter: mtredinnick | Owner: nobody
Type: Uncategorized | Status: closed
Milestone: 1.4 | Component: contrib.admin
Version: SVN | Severity: Normal
Resolution: needsinfo | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-----------------------------------------+-------------------------------
Changes (by Innogsnap):

* type: Bug => Uncategorized
* version: 1.3 => SVN
* component: Database layer (models, ORM) => contrib.admin
* milestone: => 1.4


Comment:

Hi there You do have a superb posting. At times make an article regarding
car dealer supplies. The primary reason for that is due to the fact I deal
in auto dealership supplies for vehicles of various models.

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:2>

Django

unread,
Aug 31, 2011, 2:59:55 AM8/31/11
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: | Owner: nobody
mtredinnick | Status: closed
Type: Bug | Component: Database layer
Milestone: 1.4 | (models, ORM)
Version: 1.3 | Severity: Normal
Resolution: needsinfo | Keywords:
Triage Stage: | Has patch: 0
Unreviewed | Needs tests: 0
Needs documentation: 0 | Easy pickings: 0
Patch needs improvement: 0 |
UI/UX: 0 |
-------------------------------------+-------------------------------------
Changes (by aaugustin):

* type: Uncategorized => Bug
* version: SVN => 1.3
* component: contrib.admin => Database layer (models, ORM)


Comment:

Revert spam

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:3>

Django

unread,
Feb 1, 2012, 2:31:44 PM2/1/12
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: mtredinnick | Owner: nobody
Type: Bug | Status: reopened
Component: Database layer | Version: 1.3
(models, ORM) | Resolution:
Severity: Normal | Triage Stage: Accepted
Keywords: | Needs documentation: 0
Has patch: 0 | Patch needs improvement: 0
Needs tests: 0 | UI/UX: 0
Easy pickings: 0 |
-------------------------------------+-------------------------------------
Changes (by claudep):

* status: closed => reopened
* resolution: needsinfo =>
* stage: Unreviewed => Accepted


Comment:

I've been able to reproduce it with the following code (you can insert it
in regressiontests/transactions_regress/tests.py):

{{{
def test_rollback_on_keyboardinterrupt(self):
import time
try:
with transaction.commit_on_success():
Mod.objects.create(fld=17624)

print "Hit Ctrl-C now!"
time.sleep(5)
print "Too late, and I didn't bother to return a
HttpResponse"

except KeyboardInterrupt:
pass
self.assertEqual(Mod.objects.all().count(), 0)
}}}

Unfortunately, I didn't manage to simulate a Ctrl-C programmatically, so
as to be able to include a real test. Ideas welcome.

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:4>

Django

unread,
Feb 1, 2012, 2:32:19 PM2/1/12
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: mtredinnick | Owner: nobody
Type: Bug | Status: reopened
Component: Database layer | Version: 1.3
(models, ORM) | Resolution:
Severity: Normal | Triage Stage: Accepted
Keywords: | Needs documentation: 0
Has patch: 0 | Patch needs improvement: 0
Needs tests: 0 | UI/UX: 0
Easy pickings: 0 |
-------------------------------------+-------------------------------------

Comment (by claudep):

#17624 is a duplicate with a patch

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:5>

Django

unread,
Feb 1, 2012, 4:31:37 PM2/1/12
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: mtredinnick | Owner: nobody
Type: Bug | Status: reopened
Component: Database layer | Version: 1.3
(models, ORM) | Resolution:
Severity: Normal | Triage Stage: Accepted
Keywords: | Needs documentation: 0
Has patch: 0 | Patch needs improvement: 0
Needs tests: 0 | UI/UX: 0
Easy pickings: 0 |
-------------------------------------+-------------------------------------

Comment (by claudep):

I eventually found a trick to generate the !KeyboardInterrupt to create a
failing test. Don't ask me why the os.kill has to be called twice...

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:6>

Django

unread,
Sep 20, 2016, 10:05:15 AM9/20/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: mtredinnick | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by timgraham):

`transaction.atomic()` doesn't seem to suffer from this issue. Is there
any value in adding the test (an updated one is attached)?

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:8>

Django

unread,
Sep 20, 2016, 10:05:31 AM9/20/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: mtredinnick | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timgraham):

* Attachment "16682-atomic.diff" added.

Django

unread,
Sep 21, 2016, 3:19:42 PM9/21/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* status: new => closed

* has_patch: 0 => 1
* resolution: => fixed
* stage: Accepted => Ready for checkin


Comment:

I created a [https://github.com/django/django/pull/7276 PR] and Aymeric
indicated that adding the test is useful.

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:9>

Django

unread,
Oct 14, 2016, 12:54:15 PM10/14/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* keywords: => 1.11
* status: closed => new
* has_patch: 1 => 0
* resolution: fixed =>
* stage: Ready for checkin => Accepted


Comment:

Reopening as the test hangs on the last line when I run it on Oracle
(using the Oracle DB Developer VM). I haven't seen any problems with it on
Jenkins. Can anyone else reproduce that and/or have an idea about the
cause?

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:10>

Django

unread,
Nov 22, 2016, 2:45:51 PM11/22/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* cc: felixxm (added)


Comment:

Mariusz, are you able to reproduce the hang on Oracle? Any ideas?

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:11>

Django

unread,
Nov 22, 2016, 4:23:27 PM11/22/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by felixxm):

I wasn't able to reproduce the hang on Oracle 11g/12c. I will try later
with Oracle DB Developer VM. Small suggestion is to use `signal.SIGINT`
instead of signal number.

{{{#!python
--- a/tests/transactions/tests.py
+++ b/tests/transactions/tests.py
@@ -1,6 +1,7 @@
from __future__ import unicode_literals

import os
+import signal
import sys
import threading
import time
@@ -225,8 +226,8 @@ class AtomicTests(TransactionTestCase):
with transaction.atomic():
Reporter.objects.create(first_name='Tintin')
# Send SIGINT (simulate Ctrl-C). One call isn't enough.
- os.kill(os.getpid(), 2)
- os.kill(os.getpid(), 2)
+ os.kill(os.getpid(), signal.SIGINT)
+ os.kill(os.getpid(), signal.SIGINT)
except KeyboardInterrupt:
pass
self.assertEqual(Reporter.objects.all().count(), 0)
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:12>

Django

unread,
Nov 24, 2016, 5:00:18 PM11/24/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by felixxm):

I confirmed that `test_rollback_on_keyboardinterrupt` hangs on Oracle from
Oracle DB Developer VM. I will try to figure it out in the next days.

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:13>

Django

unread,
Nov 25, 2016, 7:08:28 AM11/25/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham <timograham@…>):

In [changeset:"d391b3a85ba1166dd6c3d0c3005344ce93f22bef" d391b3a]:
{{{
#!CommitTicketReference repository=""
revision="d391b3a85ba1166dd6c3d0c3005344ce93f22bef"
Refs #16682 -- Replaced signal number with equivalent signal.SIGINT.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:14>

Django

unread,
Nov 25, 2016, 4:13:28 PM11/25/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by felixxm):

IMO it is not a Django issue. Test hangs on
​[https://github.com/django/django/blob/master/django/db/backends/base/base.py#L230
rollback], hence it is probably Oracle or cx_Oracle bug.

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:15>

Django

unread,
Nov 25, 2016, 5:54:44 PM11/25/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham):

Thanks for investigating. Since this is the only documented way we have of
running the tests on Oracle for development, is there a chance we could
skip the test when running with the Developer Days VM? Maybe the Oracle
version is different from the version on Jenkins, for example.

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:16>

Django

unread,
Dec 7, 2016, 3:01:53 PM12/7/16
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by felixxm):

Oracle DB is in the same version in both cases (12.1.0.2.0). I also
checked DB params and there is nothing unusual in them. I don't know where
is the source of the problem.

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:17>

Django

unread,
Jan 12, 2017, 5:55:35 AM1/12/17
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution:
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Josh Smeaton):

I just hit this too.

Dev Days VM: 2016-06-02_09_53_26 64 bit.
Tests OS: OSX 10.12.2
Python 3.5.2
cx_Oracle: 5.2.1

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:18>

Django

unread,
Feb 14, 2017, 11:42:02 AM2/14/17
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution: fixed

Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* status: new => closed
* resolution: => fixed


Comment:

I guess there's nothing to be done. Hopefully it's solved in a future
version of the Oracle VM.

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:19>

Django

unread,
Feb 25, 2017, 3:01:42 PM2/25/17
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham):

There's another problem with this test. When running `./tests/runtests.py
transactions --parallel=1`, this test halts execution so that only 26
tests are run. After commenting this test out, the same command runs 72
tests. Maybe it's better to remove this test for now.

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:20>

Django

unread,
Mar 9, 2017, 10:02:59 AM3/9/17
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham <timograham@…>):

In [changeset:"dfbdba924fd7cf12ce92f7a86b97590d25b75733" dfbdba92]:
{{{
#!CommitTicketReference repository=""
revision="dfbdba924fd7cf12ce92f7a86b97590d25b75733"
Reverted "Refs #16682 -- Tested transaction.atomic() with
KeyboardInterrupt."

This reverts commit d895fc9ac01db3d3420aa7c943949fe17b3ce028 since the
test is problematic as described in the ticket.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:21>

Django

unread,
Mar 9, 2017, 10:09:18 AM3/9/17
to django-...@googlegroups.com
#16682: KeyboardInterrupt not handled properly in transaction aborting
-------------------------------------+-------------------------------------
Reporter: Malcolm Tredinnick | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: 1.3
(models, ORM) |
Severity: Normal | Resolution: fixed
Keywords: 1.11 | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham <timograham@…>):

In [changeset:"e9ba8563c115ea331e7fb52b26ddb9cced5c7c94" e9ba856]:
{{{
#!CommitTicketReference repository=""
revision="e9ba8563c115ea331e7fb52b26ddb9cced5c7c94"
[1.11.x] Reverted "Refs #16682 -- Tested transaction.atomic() with
KeyboardInterrupt."

This reverts commit d895fc9ac01db3d3420aa7c943949fe17b3ce028 since the
test is problematic as described in the ticket.

Backport of dfbdba924fd7cf12ce92f7a86b97590d25b75733 from master
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/16682#comment:22>

Reply all
Reply to author
Forward
0 new messages