~jamesodhunt/ubuntu/trusty/libnih/fix-test-output-crash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
1.1/2.0
-------
alloc:
- malloc() returning NULL doesn't usually mean that we're temporarily out
  of memory these days, but out of address space or some other fault;
  looping on it is probably not the right thing to do.
- Maybe have some reserved sump pages that we use for temporary
  allocations that must succeed, and have an nih_must_alloc() function
- Some are because we can't easily deal with failure, we should try
  harder or free memory first

macros:
- audit uses of NIH_MUST and try and remove them where possible.
- NIH_ZERO is probably never right, syscalls need their errnos checked
  and action taken on just about everything except EINTR and EAGAIN
  - assert on conditions we don't know how to handle

misc:
- try and make sure each basic object type has an _init() function, this shall
  take a const void *parent which it uses for any internal allocations.
  The _new() function calls it with parent and the object set to the same
  value.
  - except when we need to separately manage the life cycle of the objects
    (e.g. current main loop code)
  - and except when references will be taken (since otherwise we'd have to
    stash the parent somewhere)
  - destructors should be mentioned in _init() documentation and chained
    in _destroy() functions
- generally start moving to function pointers being Handlers rather than
  clever names

error:
- final audit that we always push an error context before calling a
  handler function
  - use nih_error_steal() and nih_error_raise_error() to raise it in the
    parent context
- final audit that raised error is included in a new context for error
  handler functions and context popped afterwards without freeing the
  error (we expect the function to do that to indicate it actually
  handled it)

poll:
- new epoll/eventfd based loop that replaces the old main loop code
  (there's copies of this floating around that I need to merge together)

event:
- uses new poll code to wrap an eventfd() for the simplest kind of event
  handling

buffer:
- separate out buffer code into NihBuffer, it's probably useful for
  other things too; I can think of a few places where we grow strings
  and I could just use this

io:
- separate out the NihIoWatch code, this should largely go away with
  the new poll code
- separate out the NihIoMessage code into NihMessage, it behaves
  sufficiently differently that it should be separate
- the remaining code is pure buffered stream I/O
- there's a couple of tricky tests left to do:
  - nih_io_message_recv() with socket types other than PF_UNIX
  - nih_io_message_recv() when recv() fails
  - nih_io_watcher() with write error and free called

timers:
- rewrite based on new poll code and timerfd()
- clock selection and sub-second resolution
- calendar scheduled timers

signal:
- rewrite based on new poll code and signalfd()
- the API will probably change massively since you'll just add a signal
  watch, with one or more signals, rather than the set/add handler stuff

child:
- update to new signal API
- call wait() for each child signal

file:
- nih_dir_walk() is buggy and doesn't work in some situations (probably)
  - should use openat() to save string copying
  - avoid stat() where possible
  - depth-first and depth-last modes
  - parent directory fd
- add the allocating fgets() code that's floating around, rebased onto
  NihBuffer
- probably a bug in nih_file_map/unmap

watch:
- nih_watch_new() is buggy when subdirs is FALSE
  - should use openat() to save string copying
- inotify already has an IN_ISDIR flag to let us know that we got an event
  for a directory, so we don't really need to stat() it or pass a statbuf
  around; except maybe for compatibility with the walk code.
- handle IN_Q_OVERFLOW in some sane manner, at least log it.
- ideally we could rework this based off something like fanotify(), since
  it's expensive to walk large files with this
- see the Upstart conf file for the fact that this API doesn't actually
  work in practice for watching files - easier nih_watch_file() API?


dbus:
- property naming isn't consistent with D-Bus recommendations, which says
  we should use TitleCase for them, see recent D-Bus thread
- need to ignore standard/built-in D-Bus interfaces such as Peer,
  Properties and Introspectable when parsing introspection data
  - ideally have pre-canned code that would work on any proxy, would
    mean we need to generate code and link with it again

- allow structures to be named and re-used by multiple interface members
  - structure name hints come from annotations on arguments and properties
    - this means only marshal() and demarshal() need to the extra name list
      argument
    - (de)marshal_array() just passes it on
    - (de)marshal_struct() uses the first item in the name list, then passes
      on the next (need returnable pointer so we know where we got to)
    - never destroy the original list or pointer, we probably use it
      several times (each property function)
  - use annotations on annotations for the member names:
    com.netsplit.Nih.Struct		foo
    com.netsplit.Nih.StructMember	jazz
    com.netsplit.Nih.StructMember	ratchett
    - check whether the struct is already in the list, if not add it
      using the member names here, if it use the names there and warn/error on
      names here

- NihDBusProxy always tracks the remote name, which is expensive and
  annoying since you need one for every object and have to recreate them
  in every reply function and signal function
  - passing NULL for the name to the _new() function and setting the name
    by hand later is one solution
  - allowing no tracking is another
    - but required for signals, so maybe only activated if a lost handler
      is created or a signal attached?
  - create a proxy from another, could share the same name tracking code
    (in which case make it an object)
    - then find a way of getting those to reply and signal functions

- we're not using the no_reply annotation
  - object implementation probably shouldn't - the client is free to ignore
    the annotation so might be waiting for a reply, so we should send one
    anyway
  - proxy implementation is interesting, because we need to wait for a reply
    to get an error return; we wouldn't want a sync function or even a notify
    function or even a pending call :-/

- doc strings for methods, signals, arguments, etc.
  - annotation would be used to set them
  - auto-generate doc strings for output functions

- what if we want both proxy and object code in one source?
  - right now, the method names would conflict
  - arrays would need to be generated for both