source: mainline/uspace/app/viewer/viewer.c@ da904f7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since da904f7 was 1c635d6, checked in by Martin Sucha <sucha14@…>, 11 years ago

Do not hold a task's return value after it has disconnected.

Holding the task's return value meant that if nobody waited
for task's result, it polluted NS's memory. This was apparently
done because of a race between spawning a task and waiting for it.

We solve this problem in another way: ns discards the return value
as soon as the task disconnects from it. This typically happens
when the task finishes its execution. In order to avoid the race,
we send the wait request to ns while spawning the task (i.e. when
we talk to the loader), but before we allow the loaded program
to run.

Fixes #132

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/*
2 * Copyright (c) 2013 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup viewer
30 * @{
31 */
32/** @file
33 */
34
35#include <stdio.h>
36#include <unistd.h>
37#include <fcntl.h>
38#include <sys/stat.h>
39#include <errno.h>
40#include <malloc.h>
41#include <stdbool.h>
42#include <window.h>
43#include <canvas.h>
44#include <surface.h>
45#include <codec/tga.h>
46#include <task.h>
47
48#define NAME "viewer"
49
50#define WINDOW_WIDTH 1024
51#define WINDOW_HEIGHT 768
52
53static size_t imgs_count;
54static size_t imgs_current = 0;
55static char **imgs;
56
57static window_t *main_window;
58static surface_t *surface = NULL;
59static canvas_t *canvas = NULL;
60
61static bool img_load(const char *);
62
63static void on_keyboard_event(widget_t *widget, void *data)
64{
65 kbd_event_t *event = (kbd_event_t *) data;
66 bool update = false;
67
68 if ((event->type == KEY_PRESS) && (event->c == 'q'))
69 exit(0);
70
71 if ((event->type == KEY_PRESS) && (event->key == KC_PAGE_DOWN)) {
72 if (imgs_current == imgs_count - 1)
73 imgs_current = 0;
74 else
75 imgs_current++;
76
77 update = true;
78 }
79
80 if ((event->type == KEY_PRESS) && (event->key == KC_PAGE_UP)) {
81 if (imgs_current == 0)
82 imgs_current = imgs_count - 1;
83 else
84 imgs_current--;
85
86 update = true;
87 }
88
89 if (update) {
90 if (!img_load(imgs[imgs_current])) {
91 printf("Cannot load image \"%s\".\n", imgs[imgs_current]);
92 exit(2);
93 }
94 }
95}
96
97static bool img_load(const char *fname)
98{
99 int fd = open(fname, O_RDONLY);
100 if (fd < 0)
101 return false;
102
103 struct stat stat;
104 int rc = fstat(fd, &stat);
105 if (rc != EOK) {
106 close(fd);
107 return false;
108 }
109
110 void *tga = malloc(stat.size);
111 if (tga == NULL) {
112 close(fd);
113 return false;
114 }
115
116 ssize_t rd = read_all(fd, tga, stat.size);
117 if ((rd < 0) || (rd != (ssize_t) stat.size)) {
118 free(tga);
119 close(fd);
120 return false;
121 }
122
123 close(fd);
124
125 surface_t *local_surface = decode_tga(tga, stat.size, 0);
126 if (local_surface == NULL) {
127 free(tga);
128 return false;
129 }
130
131 free(tga);
132
133 if (canvas != NULL) {
134 if (!update_canvas(canvas, local_surface)) {
135 surface_destroy(local_surface);
136 return false;
137 }
138 } else {
139 canvas = create_canvas(window_root(main_window),
140 WINDOW_WIDTH, WINDOW_HEIGHT, local_surface);
141 if (canvas == NULL) {
142 surface_destroy(local_surface);
143 return false;
144 }
145
146 sig_connect(&canvas->keyboard_event, NULL, on_keyboard_event);
147 }
148
149 if (surface != NULL)
150 surface_destroy(surface);
151
152 surface = local_surface;
153
154 return true;
155}
156
157int main(int argc, char *argv[])
158{
159 if (argc < 2) {
160 printf("Compositor server not specified.\n");
161 return 1;
162 }
163
164 if (argc < 3) {
165 printf("No image files specified.\n");
166 return 1;
167 }
168
169 main_window = window_open(argv[1], true, false, "viewer");
170 if (!main_window) {
171 printf("Cannot open main window.\n");
172 return 2;
173 }
174
175 imgs_count = argc - 2;
176 imgs = calloc(imgs_count, sizeof(char *));
177 if (imgs == NULL) {
178 printf("Out of memory.\n");
179 return 3;
180 }
181
182 for (int i = 0; i < argc - 2; i++) {
183 imgs[i] = str_dup(argv[i + 2]);
184 if (imgs[i] == NULL) {
185 printf("Out of memory.\n");
186 return 4;
187 }
188 }
189
190 if (!img_load(imgs[imgs_current])) {
191 printf("Cannot load image \"%s\".\n", imgs[imgs_current]);
192 return 2;
193 }
194
195 window_resize(main_window, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,
196 WINDOW_PLACEMENT_ABSOLUTE);
197 window_exec(main_window);
198
199 task_retval(0);
200 async_manager();
201
202 return 0;
203}
204
205/** @}
206 */
Note: See TracBrowser for help on using the repository browser.